OpenMP не будет использовать все ядра? - PullRequest
2 голосов
/ 26 сентября 2011

Я пытаюсь использовать OpenMP, чтобы сделать некоторый код параллельным.

    omp_set_num_threads( 8 );
    #pragma omp parallel 
    for (int i = 0; i < verSize; ++i)
    {
        #pragma omp single nowait
        { 
            neighVec[i].index = i;
            mesh.getBoxIntersecTets(mesh.vertexList->at(i), &neighVec[i]);
        }
    }

verSize составляет около 90 КБ, а getBoxIntersecTets довольно дорогой.Поэтому я ожидаю, что код полностью использует четырехъядерный процессор.Однако загрузка процессора составляет всего около 25%.Любые идеи?

Я также пытался использовать omp параллели для конструкции, но та же история.

getBoxIntersecTets использует STL unordered_set, vector и deque, но я думаю, OpenMP должен быть независим от них, верно?

Спасибо.

1 Ответ

5 голосов
/ 26 сентября 2011

Прежде всего, #pragma omp single отключает параллельное выполнение, вы определенно не хотите этого.


Попробуйте вместо этого:

#pragma omp parallel for private(tempVec)
for (int i = 0; i < verSize; ++i)
{
    auto tempVec = neighVec[i];
    tempVec.index = i;
    mesh.getBoxIntersecTets(mesh.vertexList->at(i), &tempVec);
    neighVec[i] = tempVec;
}

Проблема с вашим исходным кодомв том, что разные потоки используют смежные элементы массива.Соседние элементы размещаются рядом друг с другом в памяти, что означает, что они, вероятно, совместно используют строку кэша.Поскольку только одно ядро ​​может одновременно иметь кеш-строку, только одно ядро ​​может выполнить работу за один раз.Или, что еще хуже, ваша программа может тратить больше времени на передачу прав собственности на строку кэша, чем на фактическую работу.

Вводя временную переменную, каждый работник может работать с независимой строкой кэша, и тогда вам нужен только доступ кстрока общего кэша в конце для хранения результатов.Вы должны сделать то же самое для первого параметра, если он передается по неконстантной ссылке.

...