CUDA noyau lancement paramètres expliqué droit?

Ici, j'ai essayé de l'auto-expliquer le CUDA de lancement des paramètres du modèle (ou l'exécution de la configuration du modèle) à l'aide de pseudo-codes, mais je ne sais pas si il y avait quelques grand erreurs, Donc j'espère que quelqu'un l'aide à la revoir, et me donner quelques conseils. Grâce avancé.

Ici, il est:

/*
normally, we write kernel function like this.
note, __global__ means this function will be called from host codes,
and executed on device. and a __global__ function could only return void.
if there's any parameter passed into __global__ function, it should be stored
in shared memory on device. so, kernel function is so different from the *normal*
C/C++ functions. if I was the CUDA authore, I should make the kernel function more
different  from a normal C function.
*/
__global__ void
kernel(float *arr_on_device, int n) {
int idx = blockIdx.x * blockDIm.x + threadIdx.x;
if (idx < n) {
arr_on_device[idx] = arr_on_device[idx] * arr_on_device[idx];
}
}
/*
after this definition, we could call this kernel function in our normal C/C++ codes !!
do you feel something wired ? un-consistant ?
normally, when I write C codes, I will think a lot about the execution process down to
the metal in my mind, and this one...it's like some fragile codes. break the sequential
thinking process in my mind.
in order to make things normal, I found a way to explain: I expand the *__global__ * function
to some pseudo codes:
*/
#define __foreach(var, start, end) for (var = start, var < end; ++var)
__device__ int
__indexing() {
const int blockId = blockIdx.x * gridDim.x + gridDim.x * gridDim.y * blockIdx.z;
return 
blockId * (blockDim.x * blockDim.y * blockDim.z) +
threadIdx.z * (blockDim.x * blockDim.y) +
threadIdx.x;
}
global_config =:
{
/*
global configuration.
note the default values are all 1, so in the kernel codes,
we could just ignore those dimensions.
*/ 
gridDim.x = gridDim.y = gridDim.z = 1;
blockDim.x = blockDim.y = blockDim.z = 1;
};
kernel =:
{
/*
I thought CUDA did some bad evil-detail-covering things here.
it's said that CUDA C is an extension of C, but in my mind,
CUDA C is more like C++, and the *<<<>>>* part is too tricky.
for example:
kernel<<<10, 32>>>(); means kernel will execute in 10 blocks each have 32 threads.
dim3 dimG(10, 1, 1);
dim3 dimB(32, 1, 1);
kernel<<<dimG, dimB>>>(); this is exactly the same thing with above.
it's not C style, and C++ style ? at first, I thought this could be done by
C++'s constructor stuff, but I checked structure *dim3*, there's no proper
constructor for this. this just brroke the semantics of both C and C++. I thought
force user to use *kernel<<<dim3, dim3>>>* would be better. So I'd like to keep
this rule in my future codes.
*/
gridDim  = dimG;
blockDim = dimB;
__foreach(blockIdx.z,  0, gridDim.z)
__foreach(blockIdx.y,  0, gridDim.y)
__foreach(blockIdx.x,  0, gridDim.x)
__foreach(threadIdx.z, 0, blockDim.z)
__foreach(threadIdx.y, 0, blockDim.y)
__foreach(threadIdx.x, 0, blockDim.x)
{
const int idx = __indexing();        
if (idx < n) {
arr_on_device[idx] = arr_on_device[idx] * arr_on_device[idx];
}
}
};
/*
so, for me, gridDim & blockDim is like some boundaries.
e.g. gridDim.x is the upper bound of blockIdx.x, this is not that obvious for people like me.
*/
/* the declaration of dim3 from vector_types.h of CUDA/include */
struct __device_builtin__ dim3
{
unsigned int x, y, z;
#if defined(__cplusplus)
__host__ __device__ dim3(unsigned int vx = 1, unsigned int vy = 1, unsigned int vz = 1) : x(vx), y(vy), z(vz) {}
__host__ __device__ dim3(uint3 v) : x(v.x), y(v.y), z(v.z) {}
__host__ __device__ operator uint3(void) { uint3 t; t.x = x; t.y = y; t.z = z; return t; }
#endif /* __cplusplus */
};
typedef __device_builtin__ struct dim3 dim3;
Il existe de nombreuses classes disponibles, y compris l'introduction de celles que vous pouvez regarder n'importe quel moment et à seulement 1 heure, ici. Essayez le GPU Computing using CUDA C de la série.
avez-vous lu ce que j'ai expliqué ci-dessous ?
Vous semblez être assez confus sur les grilles et les blocs sans parler de l'architecture sous-jacente qui est sacrément important. J'ai signé pour la ligne gratuit CUDA cours à udacity et a obtenu efficace (si pas vraiment avancé) codage en une semaine. Check it out parce que la programmation sur GPU semble avoir besoin de fondations solides.
J'ai vérifié le cours que vous avez suggéré, en particulier la partie expliquant le noyau de la configuration de lancement udacity.com/course/viewer#!/c-cs344/l-55120467/m-67074291 (commence dans ce clip, et après 3 clips), l'enseignant n'est toujours pas clairement comment le GPU distribue les tâches aux threads. Regardez cette fonction noyau, comment le compilateur élargir les codes ? Donc, beaucoup de gens ont juste dit de vous rappeler la règle, mais la règle a été mise en œuvre dans les codes ? Alors maintenant, je suis en train de lire le conducteur de l'API et OpenCL documents, veulent juste savoir ce qui s'est passé sous le capot.
Un langage de haut niveau sont faits de sorte que vous N'avez PAS à vous soucier de la façon dont le code est intégré à la machine des instructions sur le CPU. Et à chaque nouvelle génération de PROCESSEUR apporte quelque chose de nouveau, même si le jeu d'instruction est la même, ce qui se passe RÉELLEMENT est pas nécessairement la même chose sur des architectures différentes.

OriginalL'auteur blackball | 2013-10-08