J'expérimente la nouvelle fonctionnalité de parallélisme dynamique dans CUDA 5.0 (GTK 110). Je suis confronté au comportement étrange que mon programme ne renvoie pas le résultat attendu pour certaines configurations, non seulement inattendu, mais aussi un résultat différent à chaque lancement.Certaines grilles enfants ne sont pas exécutées avec le parallélisme dynamique CUDA
Maintenant, je pense avoir trouvé la source de mon problème: Il semble que certains enfants (noyaux enserre lancés par d'autres noyaux) sont parfois exécutés lorsque trop de grilles d'enfants sont donné naissance à en même temps.
j'ai écrit ce comportement un petit programme de test pour illustrer:
#include <stdio.h>
__global__ void out_kernel(char* d_out, int index)
{
d_out[index] = 1;
}
__global__ void kernel(char* d_out)
{
int index = blockIdx.x * blockDim.x + threadIdx.x;
out_kernel<<<1, 1>>>(d_out, index);
}
int main(int argc, char** argv) {
int griddim = 10, blockdim = 210;
// optional: read griddim and blockdim from command line
if(argc > 1) griddim = atoi(argv[1]);
if(argc > 2) blockdim = atoi(argv[2]);
const int numLaunches = griddim * blockdim;
const int memsize = numLaunches * sizeof(char);
// allocate device memory, set to 0
char* d_out; cudaMalloc(&d_out, memsize);
cudaMemset(d_out, 0, memsize);
// launch outer kernel
kernel<<<griddim, blockdim>>>(d_out);
cudaDeviceSynchronize();
// dowload results
char* h_out = new char[numLaunches];
cudaMemcpy(h_out, d_out, memsize, cudaMemcpyDeviceToHost);
// check results, reduce output to 10 errors
int maxErrors = 10;
for (int i = 0; i < numLaunches; ++i) {
if (h_out[i] != 1) {
printf("Value at index %d is %d, should be 1.\n", i, h_out[i]);
if(maxErrors-- == 0) break;
}
}
// clean up
delete[] h_out;
cudaFree(d_out);
cudaDeviceReset();
return maxErrors < 10 ? 1 : 0;
}
Le programme lance un noyau dans un certain nombre de blocs donné (1er paramètre) avec un nombre donné de fils chacun (2ème paramètre). Chaque thread dans ce noyau lancera ensuite un autre noyau avec un seul thread. Ce noyau enfant écrira un 1 dans sa partie d'un tableau de sortie (qui a été initialisé avec 0s).
À la fin de l'exécution, toutes les valeurs du tableau de sortie doivent être égales à 1. Mais étrangement, pour certaines tailles de blocs et de grilles, certaines des valeurs de tableau sont toujours égales à zéro. Cela signifie que certaines grilles ne sont pas exécutées.
Cela se produit uniquement si plusieurs des grilles enfants sont générées en même temps. Sur mon système de test (un Tesla K20x) c'est le cas pour 10 blocs contenant 210 threads chacun. 10 blocs avec 200 threads fournissent le résultat correct, cependant. Mais aussi 3 blocs avec 1024 threads causent chacun l'erreur. Étrangement, aucune erreur n'est signalée par le moteur d'exécution. Les grilles d'enfant semblent simplement être ignorées par le planificateur.
Est-ce que quelqu'un d'autre fait face au même problème? Ce comportement est-il documenté quelque part (je n'ai rien trouvé), ou est-ce vraiment un bug dans l'exécution du périphérique?
Cela prend tout son sens, merci pour la réponse! Je ne savais pas que l'on pouvait utiliser 'cudaGetLastError()' _inside_ un noyau. J'ai également constaté qu'il est possible d'augmenter le nombre de lancements en attente en utilisant 'cudaDeviceSetLimit (cudaLimitDevRuntimePendingLaunchCount,)'. Ce serait formidable si vous pouviez ajouter cela à votre réponse. Merci encore! –
+1, réponse éclairante. – JackOLantern