Не используйте __syncthreads()
в расходящемся коде!Все потоки или никакие потоки из данного блока должны достигать каждого __syncthreads()
в одном и том же месте.
Все потоки из одной основы (32 потока) неявно синхронизируются, поэтому вам не нужно __syncthreads()
собрать их всех вместе.Однако, если вы беспокоитесь о том, что записи в общую память одного потока могут быть не видны другому потоку той же основы, используйте __threadfence_block()
.
, чтобы прояснить важность __threadfence_block()
.Рассмотрим следующие две строки:
cptmp[tid]=(cptmp[tid]< cptmp[tid+2]) ? cptmp[tid+2] : cptmp[tid];
cptmp[tid]=(cptmp[tid]< cptmp[tid+1]) ? cptmp[tid+1] : cptmp[tid];
Он может скомпилироваться во что-то вроде этого:
int tmp; //assuming that cptmp is an array of int-s
tmp=cptmp[tid];
tmp=(tmp<cptmp[tid+2])?cptmp[tid+2]:tmp;
tmp=(tmp<cptmp[tid+1])?cptmp[tid+1]:tmp;
cptmp[tid]=tmp;
Хотя это было бы правильно для однопоточного кода, очевидно, что оно не работает для CUDA.
Чтобы избежать подобных оптимизаций, вы должны либо объявить массив cptmp
как volatile
, либо добавить это __threadfence_block()
между строками.Эта функция гарантирует, что все потоки одного и того же блока увидят общую память, записанную в текущем потоке, до того, как функция будет существовать.
Аналогичная функция __threadfence()
существует для обеспечения видимости глобальной памяти.