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

Я понимаю, что сокращение можно использовать только для типов 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 ответа

Решение

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

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

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

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

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

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

Другие вопросы по тегам