Подтвердить что ты не робот

Элегантный (и типичный) метод обхода OpenMP для комплексной переменной на С++?

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

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;
}

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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