Элегантный (и типичный) обходной путь для сокращения OpenMP на сложной переменной в C ++? - PullRequest
16 голосов
/ 23 августа 2011

Я понимаю, что сокращение можно использовать только для типов POD в C ++.Что бы вы сделали, чтобы реализовать сокращение для аккумулятора сложного типа?

complex<double> x(0.0,0.0), y(1.0,1.0);
#pragma omp parallel for reduction(+:x)
for(int i=0; i<5; i++)
{
    x += y;
}

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

Ответы [ 2 ]

9 голосов
/ 24 августа 2011

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

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

4 голосов
/ 23 августа 2011

Извините, OpenMP просто не поддерживает это в настоящее время.К сожалению, вам нужно выполнить параллельное сокращение безобразным образом, как вы уже описали.

Однако, если такое параллельное сокращение действительно часто, я хотел бы сделать конструктор, аналогичный parallel_reduce в TBB.Реализация такой конструкции довольно проста.В Cilk plus есть более мощный объект-редуктор, но я не проверял, поддерживает ли он не POD.

FYI, такого рода ограничения также можно найти в прагме threadprivate.Я тестировал с VC ++ 2008/2010 и компиляторами Intel (icc).VC ++ не может поддерживать threadprivate со структурой / классом, который имеет конструктор или деструктор (или скалярную переменную, для которой требуется инициализация вызова функции), выдавая ошибку: error C3057 , "динамическая инициализация"из "частных" символов ".Вы можете прочитать эту ссылку MSDN .Тем не менее, ICC в порядке с C3057.Вы можете видеть, по крайней мере, две основные реализации такие разные.

Я предполагаю, что поддержка параллельного сокращения на не POD будет иметь аналогичную проблему выше.Чтобы поддерживать параллельное сокращение, каждый параллельный раздел должен выделять локальную переменную потока для переменной сокращения.Таким образом, если заданная редукционная переменная не является POD, им может потребоваться вызвать определяемый пользователем конструктор. Это создает ту же проблему, что я упоминал в случае C3057.

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