CUDA: comment la somme de tous les éléments d'un tableau dans un nombre au sein du GPU?

Tout d'abord, permettez-moi de préciser que je suis pleinement conscient que ma question a déjà été posée: Bloc de réduction de CUDA Cependant, comme je l'espère, pour faire clair, ma question est un suivi, et j'ai besoins particuliers qui en font la solution trouvée par l'OP pour être impropres.

Donc, laissez-moi vous expliquer. Dans mon code, je lance un Cuda noyau à chaque itération d'un tout-boucle pour faire quelques calculs sur les valeurs d'un tableau. Comme un exemple, comme les suivantes:

int max_iterations = 1000;
int iteration = 0;
while(iteration < max_iterations)
{
    __global__ void calcKernel(int* idata, int* odata)
    {
        int i = blockIdx.x*blockDim.x + threadIdx.x;
        if (i < n)
        {
            odata[i] = (idata[i] + 2) * 5;
        }
    }

    iteration++;
}

Cependant, à côté j'ai à accomplir apparemment tâche difficile pour le GPU. À chaque itération du while boucle qui appelle le noyau, j'ai à la somme de toutes les valeurs générées au sein de odata et enregistrer le résultat dans un inttableau appelé result, à un poste au sein d'un tel tableau qui correspond à l'itération en cours. Il doit être accompli à l'intérieur du noyau ou au moins encore dans le GPU parce qu'en raison de la performance de contraintes, je ne peux que récupérer le result tableau à la fin, après toutes les itérations sont effectuées.

Un faux naïf tentative woud ressembler à quelque chose comme ce qui suit:

int max_iterations = 1000;
int iteration = 0;
while(iteration < max_iterations)
{
    __global__ void calcKernel(int* idata, int* odata, int* result)
    {
        int i = blockIdx.x*blockDim.x + threadIdx.x;
        if (i < n)
        {
            odata[i] = (idata[i] + 2) * 5;
        }
    }

    result[iteration] = 0;
    for(int j=0; j < max_iterations; j++)
    {
        result[iteration] += odata[j];            
    }

    iteration++;
}

Bien sûr, le code ci-dessus ne fonctionne pas en raison de la GPU de distribuer le code dans les threads. Afin de lear, la façon appropriée de le faire, j'ai lu d'autres questions ici sur le site au sujet de la matrice de réduction à l'aide de CUDA. En particulier, j'ai trouvé une mention à un très bon NVIDIA pdf sur un tel sujet, il en est également question dans l'ancienne DONC, la question que j'ai mentionnés au début: http://developer.download.nvidia.com/compute/cuda/1.1-Beta/x86_website/projects/reduction/doc/reduction.pdf

Cependant, alors que je comprends pleinement les étapes du code décrit dans ces diapositives, ainsi que les optimisations, je ne comprends pas comment cette approche peut-somme-réduire d'un tableau à un nombre si le code fait ouptus un éventail complet (et un de pas clair dimensions). Quelqu'un pourrait s'il vous plaît faire la lumière à ce sujet et de me montrer un exemple de comment cela pourrait fonctionner (c'est à dire comment obtenir le numéro de la sortie array)?

Maintenant, pour en revenir à la question je l'ai mentionné au début (Bloc de réduction de CUDA). Notez que sa accepté de répondre simplement suggère pour lire le pdf que j'ai lié ci-dessus - qui ne pas parler de quoi faire avec le tableau de sortie généré par le code. Dans les commentaires, l'OP il mentionne qu'il/elle a été en mesure de finishi le travail en additionnant le tableau de sortie à la CPU, qui est quelque chose que je ne peut pas le faire, puisque cela signifierait télécharger le tableau de sortie de chaque itération de mon tout-boucle. Enfin, la troisième réponse dans ce lien suggère l'utilisation d'une bibliothèque à faire - mais je suis intéressé par l'apprentissage de la maternelle façon de le faire.

Sinon, je serais aussi très intéressé par toutes les autres propositions sur la façon de mettre en œuvre ce que je suis décrites ci-dessus.

Envisagez-vous à l'aide de plusieurs grains, au lieu d'un seul?
Bien sûr, à condition que je n'ai pas de transfert de/à la mémoire GPU, l'appel de plus d'un noyau ne sera pas un problème en soi.
Je le recommande ensuite, utilisez 2 grains, 1 pour les premiers calculs, et d'un autre noyau, juste pour l'ajout, et de mettre la boucle, dans le programme d'Accueil. J'ai besoin de plus d'informations de la façon dont le programme fonctionne, mais avec le code que tu nous montres, qui peut être un moyen facile de résoudre votre problème.
Je vais maintenant essayer, mais j'ai du mal avec la dernière étape. Exactement la même chose qui a été initialement demandé dans la question j'ai fait un lien (mais qui n'a été résolu par le CPU). Il est, je suis en utilisant un noyau maintenant à faire de la réduction, mais je me retrouve avec un tableau, pas un numéro unique, et je veux réduire davantage ce tableau final à un numéro unique dans le GPU.
Dans l'exemple que je vous ai donné, le résultat de son sur le premier élément du tableau, si vous voulez, avec une seule variable (emplacement mémoire) envoyer un pointeur dans le noyau, et d'affecter cette valeur à l'emplacement où vous souhaitez que la valeur, de cette manière, lorsque vous voulez le lire, à partir de l'Hôte, ou de l'Appareil, vous pouvez simplement donner le pointeur.

OriginalL'auteur AndrewSteer | 2017-03-01