#c #cuda #atomic
#c #cuda #атомарное
Вопрос:
Как следует из руководства по программированию на cuda, я хочу вызвать функцию atomicAdd:
unsigned long long int atomicAdd(unsigned long long int* address,
unsigned long long int val);
Но, когда a вызывает это с двумя переменными:
unsigned long long int *c
и unsigned long long int sum
Я получил эту ошибку:
dotproduct_kernel.cu(23): error: no instance of overloaded function "atomicAdd" matches the argument list
argument types are: (unsigned long long *, unsigned long long)
Я не знал, что это long long int
действительно существует, поэтому я попытался long int
long
, но все терпит неудачу.
Мне нужен большой тип данных, потому что мой результат будет чем-то близким к 10 ^ 14.
Вся информация о моем устройстве. Я предполагаю, что вычислительная способность равна 1.2, верно?
Major revision number: 1
Minor revision number: 2
Name: GeForce GT 240
Total global memory: 1073020928
Total shared memory per block: 16384
Total registers per block: 16384
Warp size: 32
Maximum memory pitch: 2147483647
Maximum threads per block: 512
Maximum dimension 0 of block: 512
Maximum dimension 1 of block: 512
Maximum dimension 2 of block: 64
Maximum dimension 0 of grid: 65535
Maximum dimension 1 of grid: 65535
Maximum dimension 2 of grid: 1
Clock rate: 1340000
Total constant memory: 65536
Texture alignment: 256
Concurrent copy and execution: Yes
Number of multiprocessors: 12
Kernel execution timeout: Yes
Это полный код:
__global__ void dot (long int *a, long int *b, long int *c){
__shared__ long int temp[THREADS_PER_BLOCK];
c[0] = 0;
long index = (blockIdx.x * blockDim.x) threadIdx.x;
temp[threadIdx.x] = a[index] * b[index];
__syncthreads();
if( 0 == threadIdx.x ){
long int sum = 0;
int i;
for( i = 0; i<THREADS_PER_BLOCK; i ) {
sum = temp[i];
}
atomicAdd(c, sum); //remember of -arch=sm_11
}
}
Комментарии:
1. Это может помочь узнать, какой графический процессор у вас есть. Просматриваем примечания к
atomicAdd()
: 32-разрядные атомарные операции поддерживаются только на устройствах с вычислительными возможностями 1.1 и выше. 64-разрядные атомарные операции поддерживаются только на устройствах с вычислительными возможностями 1.2 и выше.2. Я не уверен, что может быть причиной, но помогает ли это изменить объявления этих переменных, чтобы вместо этого использовать тип
unsigned long long
? Просто предположение, но компилятор путаетunsigned long long
иunsigned long long int
.3. Я пытался, но я получил ту же ошибку, но заканчивается:
(unsigned long *, unsigned long)
На один длинный меньше.
Ответ №1:
убедитесь, что вы скомпилировали свой код с помощью -arch=sm_11 или выше (по умолчанию он скомпилирован для compute camability 1.0). Также имейте в виду, если вы используете common.mk файл включен в SDK, поскольку он может переопределить некоторые из ваших флагов.
Извините, но я был почти уверен, что минимальные требования для atomicAdd были 1.1, но, похоже, это 1.2 (который поддерживает ваш графический процессор). Я также скомпилировал ваше ядро, используя ‘unsigned long long’ (‘long int’ не является допустимым типом данных для atomicAdd). Смотрите B.11.1.1 atomicAdd(). Руководство по программированию на NVIDIA CUDA C, версия v3.2.
Атомарные функции, работающие с разделяемой памятью, и атомарные функции, работающие с 64-разрядными словами, доступны только для устройств с вычислительными возможностями 1.2 и выше.
Надеюсь, это поможет.
Комментарии:
1. Минимальное требование — sm_12. Не могли бы вы это проверить? Спасибо!