Разделяемые векторы в OpenMP - PullRequest
6 голосов
/ 31 марта 2012

Я пытаюсь парализовать программу, которую использую, и получил следующий вопрос.Получу ли я потерю производительности, если несколько потоков будут нуждаться в чтении / записи для одного и того же вектора, но разных элементов вектора?У меня такое ощущение, что моя программа едва ли становится быстрее, если ее парализовать.Возьмите следующий код:

#include <vector> 

int main(){

    vector<double> numbers;
    vector<double> results(10);
    double x;

    //write 10 values in vector numbers
    for (int i =0; i<10; i++){
        numbers.push_back(cos(i));  
    } 

#pragma omp parallel for \
    private(x) \
    shared(numbers, results)
        for(int j = 0;  j < 10;  j++){

            x  =  2 * numbers[j]  +  5;  
#pragma omp critical  // do I need this ?
            {
                results[j]  =  x;     
            }
        }

    return 0;

}

Очевидно, что настоящая программа выполняет гораздо более дорогие операции, но этот пример должен объяснить только мой вопрос.Так может ли цикл for выполняться быстро и полностью параллельно или разные потоки должны ждать друг друга, потому что, например, только один поток может одновременно обращаться к номеру вектора, хотя они все читают разные элементы вектора?

Тот же вопрос с операцией записи: нужна ли мне критическая прагма или это не проблема, поскольку каждый поток записывает в отдельный элемент результатов вектора?Я рад любой помощи, которую могу получить, и также было бы хорошо узнать, есть ли лучший способ сделать это (возможно, не использовать векторы вообще, но простые массивы и указатели и т. Д.?)Потокобезопасен в некоторых случаях, и рекомендуется использовать указатель: OpenMP и вектор STL

Большое спасибо за вашу помощь!

Ответы [ 2 ]

7 голосов
/ 31 марта 2012

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

Если вы не изменяете размер своего массива, то у меня никогда не возникало проблем с одновременными записями чтения в вектор (очевидно, до тех пор, покаЯ не пишу дважды один и тот же элемент)

Что касается отсутствия повышения производительности, критическая секция openmp замедлит вашу программу до, вероятно, того же уровня, что и использование одного потока (в зависимости от того, сколько фактически сделановне этой критической секции)

Вы можете удалить инструкцию критической секции (с учетом вышеупомянутых условий).

5 голосов
/ 31 марта 2012

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

Вы также можете поиграть со стратегией расписания, потому что, если доступ к памяти не является линейным (это в приведенном вами примере), потоки могут бороться за кеш(запись элементов в одной строке кэша).OTOH, если количество элементов задано так, как в вашем случае, и в цикле нет разветвлений (следовательно, они будут выполняться с примерно одинаковой скоростью), static, что по умолчанию равно IIRC, должно работать лучше всего.

(Кстати, вы можете объявить x внутри цикла, чтобы избежать private(x), а директива shared подразумевается IIRC (я никогда не использовал ее).)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...