Вы стали жертвой проблемы XY здесь.
Давайте начнем с проблемы Y. Ваша спин-блокировка не блокируется. Чтобы понять, почему ваша спин-блокировка не работает, вам нужно проверить, как GPU обрабатывает создаваемую вами ситуацию.Вы выпускаете деформацию, состоящую из одной или нескольких групп потоков, каждая из которых состоит из множества потоков.Выполнение деформации является быстрым, пока выполнение является параллельным, это означает, что все потоки, которые создают деформацию (волновой фронт, если вы предпочитаете), должны выполнить одну и ту же инструкцию в одновременно.Каждый раз, когда вы вставляете условие (например, цикл while
в вашем алгоритме), некоторые из ваших потоков должны следовать по маршруту, а другие - по другому.Это называется расхождение потоков.Проблема в том, что вы не можете выполнять различные инструкции параллельно.
В этом случае графический процессор может использовать один из двух маршрутов:
- Динамическое ветвление , что означает, что волновой фронт (деформация) принимает один из 2 маршрутов.и деактивирует потоки, которые должны брать другие.Затем он откатывается, чтобы забрать спящие потоки, где они были оставлены.
- Плоское ветвление , что означает, что все потоки выполняют обе ветви, затем каждый поток отбрасывает нежелательный результат и сохраняет правильныйone.
Теперь забавная часть:
Не существует правила приведения, указывающего, как GPU должен обрабатывать ветвления.
Youне имеют возможности предсказать, будет ли GPU использовать тот или иной подход, и в случае динамического ветвления нет никакого способа заранее узнать, будет ли GPU переводить в спящий режим прямой маршрут, другой - ветку с меньшим количеством потоков илитот, у кого больше.Нет возможности узнать заранее, и разные графические процессоры могут выполнять код по-разному (и будут).Один и тот же графический процессор может даже изменить свою работу с разными версиями драйверов.
В случае вашей спин-блокировки ваш графический процессор (и его драйвер, и версия компилятора, которую вы используете в настоящее время), скорее всего, используют стратегию плоского ветвления.Это означает, что обе ветви выполняются всеми потоками деформации, поэтому в принципе блокировки вообще нет.
Если вы измените код (или добавите атрибут [branch]
перед циклом), вы можете принудительно вызватьдинамическое ветвление потока.Но это не решит ваши проблемы.В конкретном случае спин-блокировки, что вы просите, чтобы GPU отключил все потоки, кроме одного .И это не совсем то, что GPU захочет сделать.Графический процессор попытается сделать обратное, и закроет единственный поток, который оценивает условие по-другому.Это действительно приведет к уменьшению дивергенции и увеличению производительности ... но в вашем случае это отключит единственный поток, который не находится в бесконечном цикле .Таким образом, вы можете получить полный фронт потоков, заблокированных в бесконечном цикле, потому что единственный, который может разблокировать цикл ... это спящий режим.Ваша спин-блокировка фактически стала взаимоблокировкой .
Теперь, на вашей конкретной машине, программа может даже работать нормально.Но у вас ровно ноль гарантирует , что программа будет работать на других машинах или даже с другими версиями драйверов.Вы обновляете драйвер и бум, ваша программа неожиданно сбивает время ожидания GPU и вылетает.
Наилучшим предложением о спин-блокировках в графических процессорах является… .не использовать их.Когда-либо.
Теперь давайте вернемся к вам Y задача .
Что вам действительно нужно, это способ вычислить сумму данных в больших двух измеренияхмассив .Так что вы действительно ищете хороший алгоритм сокращения .Некоторые из них есть в Интернете, или вы можете написать свой собственный, в зависимости от ваших потребностей.
Я просто добавлю несколько ссылок для начала, если они вам понадобятся.
Отступление о расхождении
NVIDIA - Технологическая конференция GPU 2010 Слайды
Годдек - Вводное руководство
Донован - параллельное сканирование графических процессоров
Barlas - программирование многоядерных и графических процессоров