2017-02-13 7 views
-1

Y a-t-il une commande Linux/windows qui montre le type de processeur dans un GPU Nvidia? Je ne parle pas du système d'exploitation ni du type de CPU. Je pose des questions sur les processeurs (noyaux) dans le GPU lui-même. À la fin de la journée, ils sont des transformateurs. Comment savoir s'ils ont des registres 32/64 bits et des ALU 32/64 bits? Une autre question liée à ceci, sont des instructions 64 bits, comme l'ajout de deux nombres (unsigned long int), émulés en utilisant des instructions 32 bits, par le compilateur ou quelque chose d'intermédiaire, ou ils sont exécutés nativement par le matériel?Comment savoir si les cœurs GPU Nvidia sont des processeurs 32/64 bits

Cette question n'est pas assez similaire à this, j'ai besoin d'un moyen de dire quel type de machine est le GPU lui-même. En outre, la réponse à cette question ne dit pas comment les instructions 64 bits sont spécifiquement exécutées.

+0

Je ne connais pas vraiment les GPU Nvidia, mais ces informations devraient figurer dans les fiches techniques ou dans d'autres manuels. S'il n'y a pas d'informations dans le public, vous aurez probablement besoin d'une NDA avec Nvidia pour obtenir cette information. Avez-vous accès à la documentation du GPU que vous ciblez? – fsasm

+0

Les spécifications GPU ne montrent pas ces informations. Je pense qu'il devrait y avoir une API/commande qui peut dire une telle information !!! – caesar

+0

En général, les fiches de données doivent montrer ces informations, parce que c'est leur but. Si le fournisseur ne publie pas les informations, vous n'en avez pas besoin. Le pilote avec PTX cacher tous les détails du matériel pour augmenter la portabilité. Si vous avez vraiment besoin de cette information, vous devriez contacter Nvidia. – fsasm

Répondre

0

J'ai codé deux noyaux simples. Chacun ajoute deux vecteurs de types int (32 bits)/long int (64 bits). Il se trouve sur mon GPU (Tesla K80), qui se trouve être assez nouveau et bon, les cœurs sont juste 32 bits.

Le temps double à peu près lorsque la taille du vecteur augmente.

Les noyaux sont les suivants:

__global__ void add_32(int * c, int * a, int * b) 
{ 
    int gid = blockIdx.x * blockDim.x + threadIdx.x; 
    c[gid] = a[gid] + b[gid]; 
} 

typedef long int int64; 

__global__ void add_64(int64 * c, int64 * a, int64 * b) 
{ 
    int gid = blockIdx.x * blockDim.x + threadIdx.x; 
    c[gid] = a[gid] + b[gid]; 
} 

Lorsque la taille du vecteur est de 1 élément Mega, add_32 prend environ 102,911 microsecondes, alors que add_64 prend 192,669 microsecondes. (Les temps d'exécution ont été signalés en utilisant le profileur Nvidia lors de l'exécution du binaire en mode release).

Il semble que les instructions 64 bits sont simplement émulées via des instructions 32 bits!

Cela pourrait être une solution brute-force pour savoir quel type de machines sont les noyaux GPU, mais certainement pas un élégant.

Mise à jour:

Merci à A. commentaire Clayton @ Paul, il semble que la solution ci-dessus n'est pas une comparaison équitable que la taille des données double dans le cas 64 bits. Nous ne devrions donc pas lancer les deux noyaux avec le même nombre d'éléments. Le principe correct serait de lancer la version 64 bits avec la moitié du nombre d'éléments.

Pour être encore plus sûr, considérons la multiplication vectorielle par élément au lieu de l'addition. Si le GPU émule des instructions 64 bits via des instructions 32 bits, alors il a besoin d'au moins 3 instructions de multiplication 32 bits pour multiplier 2 nombres de 64 bits en utilisant peut-être un algorithme de Karatsuba par exemple. Cela implique que si nous lancions le noyau de multiplication vectorielle 64 bits avec N/2 éléments, cela prendrait plus de temps que le noyau 32 bits avec N éléments si les multiplications 64 bits étaient juste émulées.

Voici les noyaux:

__global__ void mul_32(int * c, int * a, int * b) 
{ 
    int gid = blockIdx.x * blockDim.x + threadIdx.x; 
    c[gid] = a[gid] * b[gid]; 
} 

typedef long int int64; 

__global__ void mul_64(int64 * c, int64 * a, int64 * b) 
{ 
    int gid = blockIdx.x * blockDim.x + threadIdx.x; 
    c[gid] = a[gid] * b[gid]; 
} 

Et voici les détails de l'expérience: Times ici sont de profileur nvidia sur binaire sortie en mode: 1- noyau mul_32 avec la taille du vecteur N = 256 éléments Mega , prend 25.608 millisec. 2- Noyau mul_64 avec une taille de vecteur N = 128 éléments Mega, prend 24.153 millisec. Je suis conscient que les deux noyaux produisent des résultats incorrects, mais je pense que cela n'a rien à voir avec la façon dont le calcul est fait.

+0

La mesure de l'élément * débit * d'un ajout de vecteur en fonction de la taille de l'opérande ne détermine pas si les opérations sur une taille d'élément donnée sont prises en charge de manière native. Avec les opérations SIMD, le débit diminuerait naturellement de moitié lorsque la taille de l'opérande est doublée; par exemple, un SIMD de 512 bits fonctionnerait sur 16 opérations de 32 bits mais seulement 8 opérations de 64 bits. En outre, avec une seule opération de flux, la bande passante mémoire plutôt que le débit de calcul serait mesurée. –

+0

Je pense que vous avez raison @ PaulA.Clayton J'ai mis à jour ma solution avec une méthode différente qui tient compte de la taille des données. – caesar