2013-05-23 3 views
1

Конструкция «параллельная» OpenMP и конструкция «SIMD» (новая в версии 4.0) определяют предложение reduction, которое сообщает компилятору, какая переменная выполняется сокращение, и что является оператором сокращения. Но зачем компилятору нужен программист, чтобы сообщить ему эту информацию? Например, GCC может идентифицировать сокращения, не получая никакой помощи от программиста (см. here и here). Есть ли примеры циклов, которые нельзя сделать параллельными без указания предложения о сокращении?Почему условие сокращения OpenMP необходимо для одновременного сокращения сокращений?

+0

Я не совсем уверен, что понимаю вас, но вы, кажется, путаете векторизацию и нарезку. – steabert

+0

Я понимаю разницу между ними. Что вы имеете в виду? –

ответ

2

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

Предположим, что у вас есть код, который выполняет поиск по неупорядоченной коллекции из NUM_ITEMS пунктов, и цель состоит в том, чтобы найти все элементы, соответствующие заданным критериям и собрать их в массиве matches, а также вычислить сумму некоторого свойства этих элементов. Неважно, в каком порядке найдены предметы. Серийный код может быть что-то вроде этого:

int num_matches = 0; 
int prop_sum = 0; 

for (i = 0; i < NUM_ITEMS; i++) 
{ 
    if (criteria(item[i])) 
    { 
     match[num_matches] = item[i]; 
     num_matches++; 
     prop_sum += item[i]->some_property; 
    } 
} 

Оба num_matches и prop_sum являются переменными, значения которых накапливаются в цикле идет. Но обе переменные имеют совершенно другую семантику. Хотя возможно, что prop_sum можно вычислить как сумму частичных сумм, num_matches не может из-за его использования в качестве индекса в выходном массиве. prop_sum является типичным кандидатом для сокращения в то время как num_matches не может быть уменьшен только, но и приходится использовать явную конструкцию синхронизации для того, чтобы предотвратить скачки данных и различные темы перезаписи и тот же элемент match:

int num_matches = 0; 
int prop_sum = 0; 

#pragma omp parallel for reduction(+:prop_sum) 
for (i = 0; i < NUM_ITEMS; i++) 
{ 
    if (criteria(item[i])) 
    { 
     #pragma omp critical(update_matches) 
     { 
      match[num_matches] = item[i]; 
      num_matches++; 
     } 
     prop_sum += item[i]->some_property; 
    } 
} 

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

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

+0

Извините, но я не следую вашему примеру. Что такое сокращение, используемое для вычисления prop_sum, связано с вычислением совпадений и num_matches? Они просто вычисляются в одном и том же пути цикла/потока управления. Что мне здесь не хватает? –

+1

Вам не хватает того, чтобы компилятор выглядел одинаково - что-то добавляется к переменной на каждой итерации.Разница заключается в том, что промежуточные значения 'prop_sum' незначительны, и компилятор OpenMP может использовать частные переменные, которые уменьшаются в конце параллельного региона, чтобы получить окончательное значение. С другой стороны, промежуточные значения 'num_matches' являются значительными, и поэтому к нему нельзя применить сокращение. Разница тонкая, и компилятору может быть сложно рассказать одно от другого, поэтому явное предложение 'сокращение'. –

+2

Для другого примера, когда компилятор вряд ли автоматически определит оператора правой сокращения, см. Последний список в http://software.intel.com/en-us/articles/weird-openmp-reduction. Даже многим программистам на людях было бы трудно определить, что «+» - это правильная операция сокращения для двух переменных, которыми манипулируют с помощью & =, | =, << = и^=. –

Смежные вопросы