In früheren Versionen von CUDA wurde atomicAdd nicht für doubles implementiert, so ist es üblich, dies wie here zu implementieren. Bei der neuen CUDA 8 RC stoße ich auf Probleme, wenn ich versuche, meinen Code zu kompilieren, der eine solche Funktion enthält. Ich denke, das liegt daran, dass mit Pascal und Compute Capability 6.0 eine native Doppelversion von atomicAdd hinzugefügt wurde, die aber für frühere Compute-Funktionen nicht korrekt ignoriert wird.CUDA atomicAdd für doppelte Definition Fehler
Der folgende Code verwendet zu kompilieren und mit früheren CUDA Versionen gut laufen, aber jetzt bekomme ich diese Kompilierungsfehler:
test.cu(3): error: function "atomicAdd(double *, double)" has already been defined
Aber wenn ich meine Implementierung entfernen, ich diesen Fehler stattdessen erhalten:
test.cu(33): error: no instance of overloaded function "atomicAdd" matches the argument list
argument types are: (double *, double)
Ich sollte hinzufügen, dass ich das nur sehe, wenn ich mit -arch=sm_35
oder ähnlichem kompiliere. Wenn ich mit -arch=sm_60
kompiliere, erhalte ich das erwartete Verhalten, d. H. Nur den ersten Fehler, und eine erfolgreiche Kompilierung im zweiten Fall.
Edit: Auch ist es spezifisch für atomicAdd
- wenn ich den Namen ändere, funktioniert es gut.
Es sieht wirklich wie ein Compiler Bug aus. Kann jemand anderes bestätigen, dass dies der Fall ist?
Beispielcode:
__device__ double atomicAdd(double* address, double val)
{
unsigned long long int* address_as_ull = (unsigned long long int*)address;
unsigned long long int old = *address_as_ull, assumed;
do {
assumed = old;
old = atomicCAS(address_as_ull, assumed,
__double_as_longlong(val + __longlong_as_double(assumed)));
} while (assumed != old);
return __longlong_as_double(old);
}
__global__ void kernel(double *a)
{
double b=1.3;
atomicAdd(a,b);
}
int main(int argc, char **argv)
{
double *a;
cudaMalloc(&a,sizeof(double));
kernel<<<1,1>>>(a);
cudaFree(a);
return 0;
}
Edit: Ich bekam eine Antwort von Nvidia, die dieses Problem erkennen, und hier ist das, was die Entwickler sagen über sie:
The sm_60 architecture, that is newly supported in CUDA 8.0, has native fp64 atomicAdd function. Because of the limitations of our toolchain and CUDA language, the declaration of this function needs to be present even when the code is not being specifically compiled for sm_60. This causes a problem in your code because you also define a fp64 atomicAdd function.
CUDA builtin functions such as atomicAdd are implementation-defined and can be changed between CUDA releases. Users should not define functions with the same names as any CUDA builtin functions. We would suggest you to rename your atomicAdd function to one that is not the same as any CUDA builtin functions.
Sieht aus wie ein Fehler in CUDA 8 RC für mich. Es scheint, die native Doppel-atomicAdd() funktioniert nur mit sm_60, kann aber auch mit sm_35 gesehen werden.Vielleicht könnten Sie das lösen, indem Sie Ihre eigene Version umbenennen. – kangshiyin
@Eric Ja, Umbenennung löst es auf. Beitrag bearbeitet, um dies zu umfassen. – kalj