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

Барьеры в OpenCL

В OpenCL я понимаю, что вы можете использовать функцию barrier() для синхронизации потоков в рабочей группе. Я (вообще) понимаю, для чего они предназначены и когда их использовать. Я также знаю, что все потоки в рабочей группе должны попасть в барьер, иначе возникают проблемы. Тем не менее, каждый раз, когда я пытался использовать барьеры до сих пор, это, по-видимому, приводит к сбою моего видеодрайвера или сообщению об ошибке доступа к некорректной памяти. Я видел это на двух разных видеокартах (1 ATI, 1 NVIDIA).

Итак, мои вопросы:

  • Любая идея, почему это произойдет?
  • В чем разница между barrier(CLK_LOCAL_MEM_FENCE) и barrier(CLK_GLOBAL_MEM_FENCE)? Я прочитал документацию, но мне это было непонятно.
  • Есть ли общее правило о том, когда использовать barrier(CLK_LOCAL_MEM_FENCE) vs. barrier(CLK_GLOBAL_MEM_FENCE)?
  • Есть ли время, когда вызов barrier() с неправильным типом параметра может вызвать ошибку?
4b9b3361

Ответ 1

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

Теперь, чтобы ответить на ваш вопрос, спецификация мне тоже не была ясна, но мне кажется, что в разделе 6.11.9 содержится ответ:

CLK_LOCAL_MEM_FENCE - барьерная функция будет либо сбрасывать любые переменные, хранящиеся в локальной памяти, или очередь на забор памяти для обеспечения правильный порядок операций с памятью в локальной памяти.

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

Итак, насколько я понимаю, вы должны использовать CLK_LOCAL_MEM_FENCE при записи и чтении в пространство памяти __local и CLK_GLOBAL_MEM_FENCE при записи и чтении в пространство __global.

Я не тестировал, является ли это медленнее, но большую часть времени, когда мне нужен барьер, и у меня есть сомнения относительно того, на какое пространство памяти влияет, я просто использую комбинацию из двух, то есть:

barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);

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

Надеюсь, что это поможет.

Ответ 2

Возрождение старой-точной нити. У меня были проблемы с барьером().

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

if(someCondition){
  //do stuff
  barrier(CLK_LOCAL_MEM_FENCE);
  //more stuff
}else{
  //other stuff
}

Я понимаю, что если один или несколько рабочих элементов удовлетворяют someCondition, ВСЕ рабочие элементы должны удовлетворять этому условию, или будут некоторые, которые будут пропускать барьер. Барьеры ждут, пока все рабочие элементы не достигнут этой точки. Чтобы исправить вышеуказанный код, мне нужно немного его перестроить:

if(someCondition){
  //do stuff
}
barrier(CLK_LOCAL_MEM_FENCE);
if(someCondition){
  //more stuff
}else{
  //other stuff
}

Теперь все рабочие элементы достигнут барьера.

Я не знаю, в какой степени это относится к циклам; если рабочий элемент ломается от цикла for, он сталкивается с барьерами? Я не уверен.

UPDATE: я успешно разбил несколько программ ocl с барьером в for-loop. Убедитесь, что все рабочие элементы выходят из цикла for в одно и то же время - или, еще лучше, помещают барьер за пределы цикла.

(источник: гетерогенные вычисления с OpenCL Chapter 5, p90-91)