CUDA approfondi


précédentsommairesuivant

XVII. Gestion des erreurs

Aucune fonction de CUDA ne renvoie directement ses erreurs. Il faut faire appel à une fonction spéciale, cudaGetLastError(), qui renvoie le code d'erreur, sous forme de cudaError_t.

Toutes les fonctions du runtime renvoient donc un code d'erreur, mais dans le cas d'appels asynchrones, comme le kernel retourne immédiatement, on ne peut pas savoir si une erreur a eu lieu. Vous devez donc utiliser une fonction de synchronisation afin de pouvoir récupérer l'erreur.

Chaque erreur est effacée par la suivante et une réussite renvoie aussi un code d'erreur. Récupérer une erreur remet le compteur à la réussite.

Un kernel ne peut pas retourner de code d'erreur, on doit donc vérifier s'il peut s'exécuter sans problème avant de le lancer.

Il existe une seconde fonction pour gérer les erreurs : cudaGetErrorString(), qui prend en paramètre un code d'erreur, tel que retourné par cudaGetLastError(). Elle retourne, sous la forme d'un const char *, la description de l'erreur.

Code d'erreur Signification
cudaSuccess Pas d'erreur.
cudaErrorMissingConfiguration Configuration manquante.
cudaErrorMemoryAllocation Erreur lors de l'allocation de la mémoire.
cudaErrorInitializationError Erreur lors de l'initialisation.
cudaErrorLaunchFailure Erreur au lancement.
cudaErrorPriorLaunchFailure Erreur lors d'un lancement précédent.
cudaErrorLaunchTimeout Temps d'exécution trop long.
cudaErrorLaunchOutOfResources Plus de ressources disponibles pour l'exécution.
cudaErrorInvalidDeviceFunction Fonction invalide pour le périphérique.
cudaErrorInvalidConfiguration Configuration invalide.
cudaErrorInvalidDevice Périphérique invalide.
cudaErrorInvalidValue Valeur invalide.
cudaErrorInvalidPitchValue Valeur de pas invalide.
cudaErrorInvalidSymbol Symbole invalide.
cudaErrorMapBufferObjectFailed Erreur lors de l'accès au buffer.
cudaErrorUnmapBufferObjectFailed Erreur lors de l'accès au buffer.
cudaErrorInvalidHostPointer Pointeur sur l'hôte invalide.
cudaErrorInvalidDevicePointer Pointeur sur le périphérique invalide.
cudaErrorInvalidTexture Texture invalide.
cudaErrorInvalidTextureBinding Binding de texture invalide.
cudaErrorInvalidChannelDescriptor Descripteur de chaîne invalide.
cudaErrorInvalidMemcpyDirection Direction invalide pour memcpy.
cudaErrorAddressOfConstant Erreur dans l'adresse d'une constante.
cudaErrorTextureFetchFailed Erreur lors de l'accès à une texture.
cudaErrorTextureNotBound Texture non liée.
cudaErrorSynchronizationError Erreur de synchronisation.
cudaErrorInvalidFilterSetting Paramètre de filtre invalide.
cudaErrorInvalidNormSetting Paramètre de norme invalide.
cudaErrorMixedDeviceExecution Exécution mixte sur le périphérique.
cudaErrorCudartUnloading CUDA runtime en cours de déchargement.
cudaErrorUnknown Erreur inconnue.
cudaErrorNotYetImplemented Fonction pas encore implémentée.
cudaErrorMemoryValueTooLarge Valeur mémoire trop grande.
cudaErrorInvalidResourceHandle Handle de ressource invalide.
cudaErrorNotReady Pas encore prêt.
cudaErrorInsufficientDriver CUDA runtime plus récent que le driver.
cudaErrorSetOnActiveProcess Set on active process error.
cudaErrorNoDevice Pas de périphérique disponible.
cudaErrorStartupFailure Échec du lancement.
cudaErrorApiFailureBase Erreur dans l'API.

XVIII. Gestion des périphériques

cudaGetDeviceCount() et cudaGetDeviceProperties() permettent d'énumérer les périphériques, les cartes graphiques et leurs capacités.

 
Sélectionnez
int deviceCount;
cudaGetDeviceCount(& deviceCount);
int device;

for (device = 0 ; device < deviceCount ; ++device)
{
    cudaDeviceProp deviceProp;
    cudaGetDeviceProperties(&deviceProp, device);
}

Seuls les périphériques avec un indice de capacité de calcul supérieur ou égal à 1.0 sont retournés, les autres ne pouvant pas être exploités par CUDA.

cudaSetDevice() sert à sélectionner le périphérique qui exécutera les calculs du thread CPU.

 
Sélectionnez
cudaSetDevice(device);

Un périphérique doit être choisi avant d'appeler le moindre kernel, soit explicitement avec cudaSetDevice(), soit implicitement (le périphérique 0 est alors choisi). Tout appel ultérieur à cudaSetDevice() échouera.

La fonction cudaGetDeviceProperties() renvoie une structure ainsi définie.

 
Sélectionnez
struct cudaDeviceProp
{
    char name[256];
    size_t totalGlobalMem;
    size_t sharedMemPerBlock;
    int regsPerBlock;
    int warpSize;
    size_t memPitch;
    int maxThreadsPerBlock;
    int maxThreadsDim[3];
    int maxGridSize[3];
    size_t totalConstMem;
    int major;
    int minor;
    int clockRate;
    size_t textureAlignment;
    int deviceOverlap;
    int multiProcessorCount;
    int kernelExecTimeoutEnabled;
}
  • name : chaîne ASCII identifiant le périphérique ;
  • totalGlobalMem : mémoire globale totale disponible sur le périphérique en bytes ;
  • sharedMemPerBlock : mémoire partagée disponible pour un bloc en bytes (cette mémoire est partagée par tous les blocs de threads résidant simultanément sur un multiprocesseur) ;
  • regsPerBlock : nombre de registres 32 bits disponibles à un bloc de threads ;
  • warpSize : taille d'un warp en threads ;
  • memPitch : pas maximal en bytes permis par la copie de mémoire qui implique des régions de mémoire allouées par cudaMallocPitch(); ;
  • maxThreadsPerBlock : nombre maximal de threads par bloc ;
  • maxThreadsDim[3] : dimensions maximales d'un bloc ;
  • maxGridSize[3] : dimensions maximales d'une grille ;
  • totalConstMem : total de mémoire constante disponible sur le périphérique ;
  • major : numéro de révision majeur de la capacité de calcul ;
  • minor : numéro de révision mineur de la capacité de calcul ;
  • clockRate : fréquence de l'horloge en kilohertz ;
  • textureAlignment : alignement des textures requis, les adresses de base des textures qui sont alignées sur ceci n'ont pas besoin d'appliquer un offset lors des recherches ;
  • deviceOverlap : 1 si le périphérique peut copier de la mémoire entre l'hôte et le périphérique en même temps qu'exécuter un kernel, 0 sinon ;
  • multiProcessorCount : nombre de multiprocesseurs sur le périphérique ;
  • kernelExecTimeoutEnabled : 1 s'il y a une limite de temps pour les kernels, 0 sinon.

Vous pouvez définir vous-même une structure de ce genre et demander à CUDA de choisir le périphérique qui y correspond le mieux, grâce à la fonction cudaChooseDevice( int * dev, const struct cudaDeviceProp * prop ) (elle retourne le périphérique dans dev).


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

CUDA et le GPGPU
Introduction à CUDA
CUDA approfondi
La FAQ GPGPU & CUDA
  

Copyright © 2009 Thibaut Cuvelier. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.