Sylvain Collange

publicité
Barra : un simulateur de GPU pour CUDA
Sylvain Collange
([email protected])
Qu’est-ce qu’un simulateur ?
Les simulateurs fonctionnels émulent le comportement d’un processeur,
indépendants de l’implémentation, ou micro-architecture. Ils permettent de :
– concevoir et tester des jeux d’instructions,
– générer des traces d’exécution,
– tester et le déboguer des logiciels.
Les simulateurs niveau transaction et niveau cycle simulent une microarchitecture donnée suivant un modèle de temps, voire de consommation. Ils
permettent :
– d’instrumenter et d’optimiser les logiciels,
– d’identifier les goulets d’étranglement d’une micro-architecture,
– de quantifier l’impact de modifications micro-architecturales,
– de borner des temps d’exécution (WCET). . .
Simulateurs existants
– CPU : SimpleScalar, ooosim. . .
– GPU : Attila, Qsilver.
Un GPU : NVIDIA G80
Spécificités
– SIMD large,
– multithreading matériel massif,
– exécution transparente des branchements par prédication,
– accès mémoire par Gather et Scatter,
– mémoire hétégogène : constante, locale, globale. . .
Ces aspects ne sont pas pris en charge par les simulateurs existants.
L’architecture n’est pas documentée en détail. Il est nécessaire d’effectuer
des tests pour en comprendre le fonctionnement [1, 4]. Nous nous intéressons à l’architecture N VIDIA : G80, G92 et GT200 et à son jeu d’instruction
[5].
31
24
16
8
Les instructions sont complexes mais décomposables en sous-éléments orthogonaux : prédicat, opération, destination, sources. Chaque sous-élément
est décodé indépendamment.
Warp 3 :
@p1.leu mad.f32.rn p1|r2, s[a2+48], r0, c14[32]
Ordonnancement
Fetch
Décodage
Lecture opérandes
Ordonnanceur
masque
Masque
Exécution
&
32
mad.f32.rn
@p1.leu
Pred
W1
W2
W3
W4
@p1.leu
32
Numéro
de warp
OP
PC
mad.f32.rn
c14[32]
32x32
.leu
s[a2+48]
Warp 3
W24
Dest
p1|r2
Src1
s[a2+48]
Src2
r0
Src3
c14[32]
@p1
r0
ALU/
FPU
4x32
Registres p1
prédicat
Registres
adresse
Décodeurs
64
ID de warp
Addresse
Vecteur
Masque
Écriture
4x32
r2
32x32
32x32
Registres généraux
32x32
a2
Mémoire
Intégration avec CUDA
Un pilote virtuel sous la forme d’une bibliothèque dynamique remplace la bibliothèque N VIDIA CUDA et intercepte les appels de fonctions de l’application
ou de la couche Runtime haut-niveau de CUDA. Aucune recompilation n’est
nécessaire. Des drapeaux permettent d’activer la génération de traces.
Application
Application
CUDA Runtime
0
CUDA Runtime
Pilote CUDA
Pilote Barra
GPU
Simulateur de GPU
Mot 0
OP
Adress reg[0-1]
Adress Imm/reg
Src3 from const mem
Src2 from const mem
Src2
Src1
Dest
Flow control
Long instruction
Résultats
31
24
16
8
0
Mot 1
– Simulation correcte de la plupart des programmes du SDK CUDA.
– Vitesse d’exécution comparable à celle de l’émulation niveau source.
SubOP
Src3 neg
Src1 neg
Src2 imm
GPU execution (9800GX2)
Barra
CUDA emulation
100,000
Rounding mode
Src1 from sh mem
Src3
Pred reg
Pred cond
Set pred
Set pred reg
Dest is output reg
Adress reg[2]
Marker
Execution time
10,000
Simuler le G80
1,000
100
10
Les registres et les opérateurs sont vectoriels. Les branchements sont simulés par prédication implicite à l’aide d’une pile de masque et de plusieurs piles
d’adresses.
Code C
if(p)
{
...
}
else
{
...
}
Assembleur
@!p br else
Pile cibles
push(else)
PC = pop()
push(endif)
push(p)
pop()
transpose
scanLargeArray
reduction
matrixMul
histogram256
– Validation de propositions de modifications architecturales [2].
– Simulation niveau transaction de la mémoire et des cœurs d’exécution.
– Modèle de consommation.
– Débogueur.
p = pop()
push(p̄∧top)
Références
endif
...
endif:
Travaux futurs
Pile masques
else
...
br endif
else:
fastWalshTransform
mov.b32 s[a1+0x0030], r11
mov.b32 s[a1+0x0070], r0
bar.sync 0
mov.u32.u32.rd r0, s[a3+0x0000]
r0 = (0.794227, 0.115912, . . .)
mad.f32.rn r2, s[a2+0x0030], r0, r2 r2 = (0.309071, 0.045107, . . .)
mov.u32.u32.rd r0, s[a3+0x0010]
r0 = (0.157347, 0.436301, . . .)
MonteCarlo
0xe422c78004001801
0xe420078004003801
0x00000000861ffe03
0x0423c7801c00c001
0x00208780e800d809
0x0423c7801c00c801
0
MersenneTwisterBM
Un émulateur du jeu d’instruction N VIDIA G80 décode et exécute les instructions natives.
MersenneTwister
1
pop()
Le simulateur exécute alternativement les instructions de plusieurs threads
(warps) suivant un ordonnancement round-robin. Ces warps sont synchronisables par une instruction barrière. Les instructions d’accès mémoire Gather
et Scatter acceptent des vecteurs d’adresses.
Les bancs de registres sont implicitement indexés par le numéro de warp
courant. Les instructions sont prédiquées à la fois de manière explicite par un
registre de prédicat et de manière implicite par le masque de branchement
courant.
[1] Sylvain Collange, Marc Daumas, and David Defour. État de l’intégration de la virgule
flottante dans les processeurs graphiques. RSTI-TSI, VOL 27/6:719–733, 2008.
[2] Sylvain Collange, Marc Daumas, David Defour, and Régis Olivès. Fonctions élémentaires
sur GPU exploitant la localité de valeurs. In Actes de SYMPA, 2008. http://hal.archivesouvertes.fr/hal-00202906.
[3] Sylvain Collange, David Defour, and David Parello. Barra, a Modular Functional GPU
Simulator for GPGPU. http://hal.archives-ouvertes.fr/hal-00359342, 2009.
[4] Sylvain Collange, David Defour, and Arnaud Tisserand. Power Consuption of GPUs from
a Software Perspective. http://hal.archives-ouvertes.fr/hal-00348672, 2009.
[5] Wladimir J. van der Laan. Decuda, cudasm, 2007. http://www.cs.rug.nl/~wladimir/decuda/.
Téléchargement