Bonjour,
Tout d'abord je tiens à m'excuser si je n'ai pas posté au bon endroit mais je n'ai pas vu d'onglet "OpenCL" donc je me suis dit que poster dans le forum C ce n'était pas le plus stupide.
Je vais vous expliquer mon problème en détails et j'aurai pas mal de questions aussi je remercie vraiment tous ceux qui prendront ne serait-ce que la peine de lire. Je ne posterai pas toutes les informations que j'ai car ça ferait beaucoup, si il vous manque quelque chose n'hésitez pas. Alors voilà ... !
J'ai écrit pour un mini-projet à l'école une implémentation de l'interpolation de Shepard en C++ (pas besoin de savoir ce que c'est pour m'aider je pense). Aujourd'hui dans le cadre du même cours C, je dois la réécrire en utilisant OpenCL pour l'accélérer.
Je vous poste la signature des trois fonctions et la définition de l'une d'entre elles pour vous poser les questions auxquelles j'aimerai beaucoup avoir des réponses !
Code : Sélectionner tout - Visualiser dans une fenêtre à part void computeDistances(const int DIM, const int nPoints, const double *knownCoords, const int nGrids, const double *gridCoords, double *distances)
Code : Sélectionner tout - Visualiser dans une fenêtre à part void computeWeights(const int nGrids, const int nPoints, double *distances, double *weightSum, const double p)Voici la fonction computeWeights :
Code : Sélectionner tout - Visualiser dans une fenêtre à part void computeInterpolation(const int nValues, const int nGrids, const int nPoints, const double *distances, const double *weightSum, const double *knownValues, double *gridValues)
Voici maintenant les signatures des nouvelles fonctions qui nous ont été imposées par mon enseignant. (les fonctions qui doivent préparer les kernels, les configurations et "launch" les kernels)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 void computeWeights(const int nGrids, const int nPoints, double *distances, double *weightSum, const double p){ /* Compute weights from known points to each grid point nPoints - Number of known data points nGrids - number of points in the grid distances - array containing all the distances all data points and all grid points weightSum - array containing the weight sums of each grid point p - parameter to compute sums */ for(int i = 0; i < nGrids; i++){ double weight(0.0); for(int j = 0; j < nPoints; j++){ double this_weight(0.0); if(distances[i * nPoints + j] == 0){ weight = 0.0; break; } this_weight = 1.0 / pow(distances[i * nPoints + j], p); weight += this_weight; distances[i * nPoints + j] = this_weight; } weightSum[i] = weight; } }
Sachant que dans le cours on a travaillé sur un problème à une seule dimension et que dans ces fonctions il y en a 2 ou 3 et que dans deux d'entre elles à un moment je break, vous pouvez imaginer que ce n'est pas évident (c'est mon premier projet de OpenCL ever).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 void computeDistances(cl::CommandQueue &cmdQueue, cl::Program &prog, const int DIM, const int nPoints, cl::Buffer &knownCoords, const int nGrids, cl::Buffer &gridCoords, cl::Buffer &distances); void computeWeights(cl::CommandQueue &cmdQueue, cl::Program &prog, const int nGrids, const int nPoints, cl::Buffer &distances, cl::Buffer &weightSum, const MY_DATA_TYPE p = 2.0); void computeInterpolation(cl::CommandQueue &cmdQueue, cl::Program &prog, const int nValues, const int nGrids, const int nPoints, cl::Buffer &distances, cl::Buffer &weightSum, cl::Buffer &knownValues, cl::Buffer &gridValues);
Voici mes questions (j'en ai à propos des fonctions au dessus et à propos des kernels qu'elles utilisent) :
Tout d'abord à propos des fonctions :
Comme on peut le voir si on prend la première fonction par exemple, il y a un paramètre const int DIM, sachant qu'un kernel utilise des types OpenCL si je ne dis pas de bêtises, dois-je caster ce const int en cl::uint ? et de même pour tous les autres paramètres.
Des tableaux de double sont passés en paramètres, est-il absolument obligatoire en OpenCL d'utiliser les types vector (par exemple double16, si oui comment s'en sortir quand le tableau a 10 000 éléments) ?
Dans mes fonctions la plupart du temps il y a une dimension bien plus grande que l'autre par exemple, DIM prendra les valeurs 2 ou 3, nValues de 1 à 10 sans doute et nPoints ou gridCoords pourraient valoir 10000 ou plus. Cela influence t-il la manière de gérer NDRange (si oui comment ? :p) Jusqu'ici moi j'ai décidé d'utiliser les trois dimensions de NDRange et j'ai écrit :
Pour les kernels,
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 size_t group_size = 8; cl::NDRange local(group_size, group_size); cl::NDRange global(nGrids*nPoints + pow(group_size, 2.0) - 1 / pow(group_size, 2.0));
typiquement j'ai cru comprendre que une boucle for ça se remplaçait par une condition sur l'id d'un work-item, puis-je en déduire que un code comme ceci en c++
peut s'écrire comme ça en OpenCL
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 for(int i = 0; i < nGrids; i++){ double weight(0.0); for(int j = 0; j < nPoints; j++){ double this_weight(0.0);
Par ailleurs je m'inquiète de savoir dans quelle espace d'adresse se situe weight et this_weight, j'ai lu dans les spécifications que par défaut ça va dans __private je crois, cela posera t-il problème ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 if(i < nGrids){ double weight = 0.0; if(j < nPoints){ double this_weight = 0.0;
Comme vous pouvez le voir à un moment dans compute_weights je break, que dois-je faire pour écrire ce code à l'aide d'OpenCL ?
Je sais que ça fait beaucoup aussi je vous remercie tous, et si quelqu'un peut répondre ne serait-ce que à une question, ou même donner un conseil sur l'orientation à suivre ça m'aiderait beaucoup.
Immo
Partager