2017-01-05 14 views
0

У меня есть этот серийный код:OpenMP: Упорядоченный график (статический) Кусок последовательность

std::vector<T> input, output; 
//populate input 
for (size_t i=0 ; i < input.size() ; i++){ 
    output.push_back(//something using input[i]); 
} 

Заметьте, что это важно, что output[i] вычисляется с использованием input[i]. Теперь я хочу распараллелить его. Простым решением является:

std::vector<T> input, output; 
//populate input 
#pragma omp for schedule(dynamic) ordered 
for (size_t i=0 ; i < input.size() ; i++){ 
    #pragma omp ordered 
    output.push_back(//something using input[i]); 
} 

Однако, это может быть очень неэффективным (ordered требует, чтобы получить замок, который генерирует большую нагрузку, если выполняется много раз, и, кроме того, если размер порции небольшие это порождает еще больше накладных расходов). Другим возможным решением может быть заполнить каждый кусок по отдельности, а затем объединить их (в упорядоченном пути):

std::vector<T> input, output; 
//populate input 
#pragma omp parallel 
{ 
    std::vector<T> myOutput; 
    std::vector<int> myIndexes; 
    #pragma omp for schedule(static,1) //NOTICE STATIC! 
    for (size_t i=0 ; i < input.size() ; i++){ 
    myOutput.push_back(//something using input[i]); 
    myIndexes.push_back[i]; 
    } 
    #pragma omp for ordered schedule(static) 
    for(int i=0 ; i<omp_get_num_threads() ; i++){ 
    #pragma omp ordered 
    { 
     std::cout<<"Hello from thread "<<omp_get_thread_num()<<": "; 
     for(size_t j = 0; j < myIndexes.size(); j++) 
     std::cout<<indexes[j]<<" "; 
     std::cout<<std::endl; 
    } 
    } 
} 

Предположив, что input.size()=10 и у нас есть 8 ядер. Это то, что я хочу быть распечатаны:

Hello from thread 0: 0 1 
Hello from thread 1: 2 3 
Hello from thread 2: 4 
Hello from thread 3: 5 
Hello from thread 4: 6 
Hello from thread 5: 7 
Hello from thread 6: 8 
Hello from thread 7: 9 

Но это является то, что он на самом деле напечатал:

Hello from thread 0: 0 8 
Hello from thread 1: 1 9 
Hello from thread 2: 2 
Hello from thread 3: 3 
Hello from thread 4: 4 
Hello from thread 5: 5 
Hello from thread 6: 6 
Hello from thread 7: 7 

Код в this вопрос может решить мой случай, но это своего рода обман (это фактически не используя #pragma omp parallel for).

Возможно ли получить желаемое поведение, используя только openmp?

+0

Вы попробовали 'schedule (static, 2)' вместо 1? – Gilles

+0

Нет, но это не имеет значения: в этом случае вам просто нужно три элемента на поток, которые мы находимся в той же ситуации до – justHelloWorld

ответ

1

Наиболее простым решением является использование operator[] вместо push_back.

std::vector<T> input, output; 
//populate input 
output.resize(input.size()) 
#pragma omp parallel for 
for (size_t i=0 ; i < input.size() ; i++){ 
    output[i] = //something using input[i]); 
} 

Теперь это делает предполагает, что T является DefaultInsertable. Если нет, вы можете использовать конкретный аргумент фиктивного значения для resize.

BTW: Я не понимаю ваш ожидаемый результат. Почему вы ожидаете, что индекс будет отображаться несколько раз в разных потоках?

Редактировать:

В спецификации OpenMP четко говорит о static планирования (таблица 2.5).

ломти назначены нити в команде в циклическом режиме в порядке нити числа.

Таким образом, фактический результат соответствует.

+0

Извините, я отредактировал мой желаемый результат. Однако я считаю, что ваше решение выполнимо. Я уже думал об этом и отбросил его, но теперь, когда я прочитал его снова, это возможно. Однако остается проблема «статического» и желаемого выпуска. – justHelloWorld

+0

Я добавил объяснение относительно статического планирования. – Zulan

+0

Да, я прочитал эту цитату, но я надеялся, что кто-то придумал другую политику планирования, чем круглая. Я думаю, что мое решение единственное в этом пункте. – justHelloWorld