2017-06-23 2 views
0

J'ai un noyau.clEnqueueNDRangeKernel N'exécute pas sur toute la plage globale

__kernel void unprimed_grid_int(__global double *ar_u,   
           __global double *ap_u,   
           __global double *az_u,   
           __global const double *x_p,  
           __global const double *y_p,  
           __global const double *z_p,  
           __global const double *jx_p,  
           __global const double *jy_p,  
           __global const double *jz_p,  
           const uint nr,     
           const uint nz,     
           const uint nv,   
           const double rmin,  
           const double dr,  
           const double zmin,  
           const double dz,  
           const double dv, 
           const double dvol, 
           const uint p_size, 
           const uint offset) { 

    const size_t i = get_global_id(0); 

    const size_t ri = (i + offset)%nr; 
    const size_t zi = ((i + offset)/nr)%nz; 
    const size_t vi = ((i + offset)/(nr*nz))%nv; 

    const double r = ri*dr + rmin; 
    const double z = zi*dz + zmin; 
    const double v = vi*dv; 

    const double x = r*cos(v); 
    const double y = r*sin(v); 

    double ax = 0.0; 
    double ay = 0.0; 
    double az = 0.0; 

    for (uint j = 0; j < p_size; j++) { 
     const double dx = x_p[j] - x; 
     const double dy = y_p[j] - y; 
     const double dz = z_p[j] - z; 

     const double rp = sqrt(dx*dx + dy*dy + dz*dz); 

     ax += jx_p[j]/rp; 
     ay += jy_p[j]/rp; 
     az += jz_p[j]/rp; 
    } 

    ax *= dvol; 
    ay *= dvol; 
    az *= dvol; 

    ar_u[i] += x/r*ax + y/r*ay; 
    ap_u[i] += -y/r*ax + x/r*ay;        
    az_u[i] += az;            
} 

que j'appelle de

const size_t offset = 0; 
    clEnqueueNDRangeKernel(device->queue, device->kernels["int"], 1, &offset, &device->u_chunk, NULL, static_cast<cl_uint>(wait.size()), wait.data(), &event); 

avec une taille de travail global (device->u_chunk) de 734208. Cependant le noyau, lorsqu'il est exécuté sur mon GPU, ne fonctionne que sur les premiers 2560 éléments de travail . J'ai vérifié la taille de travail globale à l'intérieur du noyau en imprimant la valeur de get_global_size(0). Si j'ajoute une instruction d'impression pour vérifier quels éléments de get_global_id(0), il fonctionne sur toute la gamme.

Qu'est-ce qui empêcherait un noyau de fonctionner sur toute la plage?

Mise à jour

Pour ajouter un ajouter un exemple de ce qui se passe, voici un graphique de la sortie de code. Plot of the ap_u buffer Comme vous pouvez le voir, le noyau n'a pas fonctionné sur toute la gamme. Pour mieux le démontrer, j'ai exécuté le scénario de test suggéré par l'une des réponses. J'ai modifié mon noyau pour ajouter un argument supplémentaire.

__kernel void unprimed_grid_int(..., __global uint *test) { 
    ... 
    if (get_global_id(0) == 5) { // Reran with 5 changed to 700000 
     test[0] == 10; 
    } 
} 

Pour l'identifiant global ci-dessous où la sortie semble coupure (2560), je l'ai lu en arrière la valeur correcte de 10. Pour une valeur identifiant globale au-dessus du seuil, je reçois la valeur incorrecte retournée.

+1

Je suppose que c'est vraiment sur toute la gamme (votre deuxième printf le prouve) mais votre printf de global_size est en quelque sorte incorrect. – Dithermaster

Répondre

0

J'ai compris pourquoi mon noyau ne fonctionnait pas à l'échelle globale. Le problème provient de la boucle for dans le noyau. p_size est de l'ordre de 700000 itérations. Cela a causé beaucoup de temps au noyau pour l'exécution du noyau. Depuis mes GPU sont connectés à des affichages, the kernel is timing out de sorte que le UI doesn't lock up.

2

Je pense que cela fonctionne sur tous les éléments, mais l'impression de toutes les valeurs ne fonctionne pas correctement, car il y a beaucoup de threads.

Pour vous assurer qu'il fonctionne, vous pouvez également ajouter une variable entière comme argument du noyau et procédez comme suit:

__kernel void unprimed_grid_int(your_arguments, int test) { 

    if (get_global_id(0) == 734207) { 
     test = 10; // or any other value 
    } 
} 

Puis, après que le noyau est exécuté, si tous les éléments sont traités, il devrait être 10 ou quel que soit le nombre que vous utilisez.

+0

J'ai essayé ceci pour deux valeurs globales id au-dessus et au-dessous du 2560. Dans les deux cas la valeur de l'entier de test n'a jamais changé. – user1139069

+0

@ user1139069 avez-vous lu la valeur en utilisant clEnqueueReadBuffer? – vgeclair

+0

J'ai réimplémenté le test en tant qu'objet 'cl_mem' et réanalysé. Pour un ID global de 5, j'obtiens la valeur correcte retournée. Pour un identifiant global de 700000, la valeur est inchangée. – user1139069