Bonjour,
Je travaille actuellement sur projet où je dois paralléliser en CUDA un projet existant en C++ et j'aimerais que le code puisse compiler à la fois en utilisant CUDA mais fonctionne quand même sans. Pour faire ça, je souhaite avoir des classes qui puissent être utilisés à la fois sur le CPU et le GPU. J'ai donc fait une macro qui ajoute __host__ et __device devant les méthodes de la classe et mit aucune méthode en virtual (excepté le destructeur mais je ne sais pas si je dois l'enlever vu que j'ai lu que le polymorphisme et les méthodes virtuelles n'étaient pas pleinement prit en charge par nvcc) pour avoir une classe de la forme suivante :
https://pastebin.com/96ch1RH5
J'utilise donc la macro __CUDACC__ pour savoir si j'utilise CUDA ou pas. Cependant quand j'ai testé un code rapide, j'ai remarqué que même quand j'utilise nvcc, __CUDACC__ n'est pas défini si l'extension du fichier est .hpp mais l'est si l'extension est .cu alors __NVCC__ l'est tout le temps. Je ne comprends pas trop donc le fonctionnement réel de la définition des macros utilisées par nvcc et laquelle utilisé pour mon cas (et aussi quel nom d'extension choisir pour des fichiers qui définissent des éléments utilisables en CUDA et en C++) ?
Merci d'avance pour votre aide.
Ps: Je ne parallélise pas la classe de vecteur car je vais utilisé que des Vec3 et que je vais paralléliser sur une liste de structure qui contient ces vecteurs (c'est une simu physique à base de particules), à moins qu'il soit préférable de quand même utiliser des kernels pour ça et lancer d'autres kernels dans les kernels principaux ?
nvcc ne compile pas le code de la meme facon si c'est un .cpp ou un .cu.
Si c'est un .cpp, le code est passe tel quel au compilateur sous jacent.
Ce que tu veux c'est certainement rajouter ton flag a toi pour dire si tu compile avec support pour GPU ou pas. Typiquement ca va dans ton Makefile.
Avec ce flag, tu peux avoir le code qui n'est pas du code CUDA savoir si il compile dnas un context ou l'acceleration par GPU est utile.
Sinon, une raison particuliere d'utiliser CUDA plutot que OpenACC? OpenACC est beaucoup plus simple a ecrire, et il y a une chance que tes physiciens puissent modifier le code a posteriori.
Le 25 avril 2019 à 09:35:47 Technoforce3 a écrit :
Ps: Je ne parallélise pas la classe de vecteur car je vais utilisé que des Vec3 et que je vais paralléliser sur une liste de structure qui contient ces vecteurs (c'est une simu physique à base de particules), à moins qu'il soit préférable de quand même utiliser des kernels pour ça et lancer d'autres kernels dans les kernels principaux ?
En general, c'est une mauvaise idee de lancer un kernel dans un autre kernel. Ca peut etre utile dans certains algo, comme de l'AMR, mais ce sont des cas assez facilement reconnu.
Je suis en stage dans un labo de recherche en informatique et l'écriture en CUDA est une requête de mes encadrants.
Du coup j'ai du mal à voir comment j'utilise ça dans mon fichier. Ce qui contient les macro __host__ et __kernel__ est dans des fichiers cpp, nvcc va donc les ignorer ? Si je lance un kernel dans un fichier dont l'extension est cpp, cela va fonctionner ? Quand j'ai vu CUDA en cours, on avait que des fichiers .cu mais comme là j'aimerais que l'application fonctionne dans les deux cas (principalement pour me faciliter la vie quand je devrais faire des comparatifs pour voir le gain par CUDA), j'aurais trouvé plus logique de tout mettre dans des .cpp (sauf pour les kernels que j'aurais mit dans des fichiers à part .cu) et faire passer nvcc dessus quand on veut utiliser CUDA.
La semantique est qu'un fichier .cpp est du code C++.
nvcc doit savoir quoi faire d'un kernel launch. Donc clairement un kernel launch n'est pas du code C++. Donc ca n'a rien a faire dans un .cpp.
Et probablement les appels au runtime cuda sont potentiellement configurer par nvcc aussi, donc c'est probablmeent aussi pas dans un fichier .cpp.
Mais du coup je fais comment pour mes fichiers qui peuvent contenir du code qui s'exécutent sur device ou sur host (ma classe Vec par exemple)? Autant je peux faire un fichier, qui contiendra les lanceurs de noyau qui seront appelés par les classes c++ pour les mettre dans un fichier .cu, autant pour les structures qui seront instanciés sur le GPU si j'ai un GPU NVidia ou sur le CPU dans le cas contraire, ça me fait bizarre de le mettre dans .cu
https://devblogs.nvidia.com/separate-compilation-linking-cuda-device-code/
Si je comprends bien, faut que j'ajoute l'option -x cu
pour que nvcc passe sur les .cpp pour ma classe Vec ?
Désolé du triple-post. Je pense qu'au final, je vais plutôt faire des classes séparés entre ce qui utilise du CUDA et ce qui est du CPU et changer un attribut dans la classe qui les contient avec un #ifdef, ça va me faire des copier-coller mais sera moins galère pour configurer
bah tu peux mettre ca dans un .hpp. Je ne comprends pas le probleme.
Bon au final, après les discussions avec les encadrants ça va se faire autrement donc le problème va être réglé
Ça me plaît pas trop de tout mettre dans le header, c'est quand même mieux de séparer déclaration et définition quand on peut