GPU Drano est un outil d'analyse statique pour les programmes GPU. L'une des analyses de GPU Drano est de trouver des accès à la mémoire perdue dans le code CUDA. L'autre analyse soutenue par GPU Drano est une analyse pour prouver l'indépendance de la taille des blocs des programmes GPU.
Film GPUS moderne dans les filetages dans les chaînes. Tous les threads d'une chaîne effectuent des opérations dans Lockstep. Les accès à la mémoire à différents emplacements de mémoire peuvent être fusionnés en une seule charge / stockage si la mémoire est adjacente ou assez proche en mémoire. Lorsque la mémoire accessible par une chaîne est éloignée, plusieurs charges / magasins sont nécessaires pour terminer la transaction de mémoire, et nous disons que l'accès n'est pas coalé .
Un noyau GPU serait indépendant de la taille d'un bloc , si la modification de la taille de bloc tout en gardant le nombre total de threads, ne brise pas la fonctionnalité du programme. Ceci est essentiel pour le réglage correct de la taille des blocs dans les programmes GPU, qui est souvent utilisé pour améliorer les performances du programme.
Nous avons également mis en œuvre une analyse dynamique pour identifier les accès non coaloriques, il est disponible dans ce référentiel.
GPU Drano est implémenté en tant que compilateur pour LLVM à l'aide de l'implémentation Open Source CUDA de Google: gpucc . Par conséquent, Drano est étroitement couplé avec LLVM.
Drano nécessite LLVM version 6.0 ou version ultérieure. Il nécessite également CUDA Toolkit (version 7.5 ou version ultérieure) de NVIDIA. Il a été testé sur Ubuntu 16.04 LTS, mais devrait fonctionner avec la plupart des systèmes Linux existants.
L'analyse statique elle-même ne nécessite pas de GPU. Cependant, pour exécuter les programmes et pour exécuter une anlaysis dynamique, un GPU NVIDIA et des pilotes compatibles sont nécessaires. Vérifiez les exigences du système de Nvidia pour plus d'informations.
Les détails de l'algorithme et des choix de conception peuvent être trouvés dans les articles suivants:
Le script installnrun.sh inclus avec le projet détaille les étapes nécessaires pour créer et exécuter GPU Drano sur un système Ubuntu. Pour exécuter le script,
ROOT_DIR sur le chemin du dossier vers le dossier téléchargé.sh installnrun.shCela installerait automatiquement GPU Drano sur un système Linux. Nous décrivons en outre les étapes d'installation pour l'installation de l'analyse d'accès non coalescées ici. L'installation de l'analyse de l'indépendance de la taille des blocs (également appelée analyse d'invariance de taille de bloc) peut être effectuée de manière similaire.
Obtenez la source LLVM:
Assurez-vous que subversion est installée. Téléchargez la dernière version de LLVM:
svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
Obtenez la source de Clang:
Modifiez votre répertoire de travail actuel en llvm/tools/ et consultez clang à partir du référentiel SVN:
svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
Ajouter GPU Drano à LLVM:
Copiez le dossier src/ GPU Drano dans le répertoire llvm/lib/Transforms/UncoalescedAnalysis dans votre code source:
cp -r src/abstract-execution/* llvm/lib/Transforms/UncoalescedAnalysis
cp -r src/uncoalesced-analysis/* llvm/lib/Transforms/UncoalescedAnalysis
Cela créera un dossier appelé llvm/lib/Transforms/UncoalescedAnalysis/ . Nous devons enregistrer notre laissez-passer avec le système de construction LLVM, cmake . Par conséquent, appelez add_subdirectory(UncoalescedAnalysis) à llvm/lib/Transforms/CMakeLists.txt
Exemple de fichier cmakelists.txt:
$> more CMakeLists.txt
add_subdirectory(Utils)
add_subdirectory(Instrumentation)
add_subdirectory(InstCombine)
add_subdirectory(Scalar)
add_subdirectory(IPO)
add_subdirectory(Vectorize)
add_subdirectory(Hello)
add_subdirectory(ObjCARC)
add_subdirectory(Coroutines)
add_subdirectory(UncoalescedAnalysis)
Build LLVM et GPU Drano:
À partir du répertoire racine de Drano, créez une build/ répertoire. Ensuite, modifiez le répertoire dans la build/ répertoire. Assurez-vous que CMake est installé sur le système. Exécutez les commandes suivantes ici:
cmake ../llvm
make
C'est cmake avec le répertoire Path to LLVM ( ../llvm ). CMake configure LLVM pour votre système. Il devrait générer plusieurs fichiers dans votre répertoire de travail actuel ( build/ ). La commande make des builds llvm et drano.
Idéalement, utilisez make -j N où n est votre nombre de noyaux à construire en parallèle car LLVM prend beaucoup de temps à construire.
AVIS : LLVM Build prend une grande quantité de mémoire à compiler, en particulier à l'étape de liaison. Si vous avez <8 gigaoctets de RAM, LLVM peut ne pas construire. Si c'est le cas, vous pouvez make l'option -j . Cela ne recompilera que les parties défaillantes de la construction, tout en évitant plus de temps que de ne pas utiliser -j dès le début.
Installez LLVM et GPU DRANO Effectuez sudo make install . Cela devrait installer les bibliothèques et les binaires dans l'emplacement par défaut (ou l'emplacement spécifié). S'il est installé localement, ce guide suppose que Bash peut trouver la commande dans son chemin.
Ce qui précède est un guide de démarrage rapide. Si vous n'êtes pas familier avec LLVM, vous pouvez trouver tous les détails pour l'installation à: http://llvm.org/docs/gettingstarted.html
Le script installnrun.sh décrit brièvement le processus pour créer des pilotes Nvidia, Toolkit et le SDK. Le script a été commenté pour éviter le risque de remplacer les conducteurs NVIDIA existants. Notez que nous n'avons besoin que de la boîte à outils et du SDK pour exécuter l'analyse statique. Nous avons également besoin de chauffeurs et d'un GPU fonctionnel pour exécuter eux-mêmes une analyse dynamique et des programmes CUDA.
Installez les pilotes NVIDIA, la boîte à outils CUDA et le SDK: veuillez vous référer au Guide d'installation NVIDIA pour les instructions.
En résumé, si vous utilisez une distribution Linux récente et populaire, vous devriez pouvoir utiliser l'outil de téléchargement automatique pour installer les pilotes et SDK requis.
Si vous avez déjà installé les pilotes et SDK requis, vous pouvez ignorer cette étape. Ce n'est probablement pas une bonne idée de remplacer vos pilotes existants car cela pourrait rendre votre système inutilisable.
Vous pouvez avoir besoin de G ++ - Multilib pour installer les bibliothèques nécessaires requises par clang .
Cette étape est facultative . Un simple programme CUDA comme "Hello World" devrait désormais compiler en utilisant clang ou clang++ :
clang -x cuda helloWorld.cu
L'option -x cuda indique explicitement la langue. Vous pouvez l'omettre également et Clang déduire cela en tant que programme CUDA.
AVIS: Votre installation de Clang peut ne pas être en mesure de trouver plusieurs fonctions LLVM internes, si c'est le cas, vous devrez peut-être inclure -lcudart . Vous devrez peut-être également pointer vers l'emplacement du cudart.so .
Exemple:
clang -x cuda -L /usr/local/cuda/targets/x86_64-linux/lib/ -lcudart helloWorld.cu
Le chemin vers votre Cudart, donc peut être différent en fonction de votre système.
LLVM aurait dû générer un fichier d'objet partagé .so , appelé LLVMUncoalescedAnalysis.so , sous la build/lib/ répertoire.
Le clang LLVM Completier génère un périphérique séparé (le code du noyau GPU) et l'hôte (code exécuté sur les fichiers IR) lors de la compilation des programmes CUDA. GPU Drano analyse les fichiers IR LLVM pour le code de périphérique.
Par exemple, analysons le code du noyau Rodinia pour la référence gaussian . Nous changeons le répertoire en rodinia_3.1/cuda/gaussian/ .
Nous avons d'abord des fichiers IR LLVM générés pour le code qui nous intéresse:
clang++ -S -g -emit-llvm gaussian.cu
Remarquez que nous compilons avec le symbole de débogage -g , pour conserver les informations de débogage sur les emplacements du code source dans l'IR généré. Ceci est utilisé pour pointer des emplacements de code source avec des accès potentiels non coaloriques à partir de LLVM IR.
La compilation génère deux fichiers:
gaussian-cuda-nvptx64-nvidia-cuda-sm_20.ll
gaussian.ll
Nous pouvons ensuite exécuter l'analyse statique via opt de LLVM en spécifiant le chemin d'accès au binaire GPU Drano et en spécifiant le PASS -interproc-uncoalesced-analysis à être exécuté. Cette passe est une analyse interprocédurale pour détecter les accès non coaloriques. Il commence par l'analyse de la fonction la plus élevée dans le graphique d'appel, puis procède à l'analyse de ses callees dans un ordre topologique. Lors de l'analyse d'une callee spécifique, il considère la jonction des contextes d'appel de tous ses appelants. Pour exécuter une analyse intraprocédurale (qui suppose que tous les arguments de fonction initiaux sont indépendants de l'identification du thread), spécifiez -uncoalesced-analysis à être exécutée, au lieu de -interproc-uncoalesced-analysis .
opt -load ../../../build/lib/LLVMUncoalescedAnalysis.so -instnamer -interproc-uncoalesced-analysis < gaussian-cuda-nvptx64-nvidia-cuda-sm_20.ll > /dev/null 2> gpuDranoResults.txt
Remarque opt Lire le fichier IR à partir de l'entrée standard. opt écrit sa propre sortie sans intérêt pour standard, donc nous le redirigeons vers la sortie de GPU DRANO /dev/null est écrit en erreur standard qui peut être redirigé vers un fichier.
Pour générer des résultats d'analyse verbeux (LLVM IR annoté avec les informations d'analyse), exécutez opt avec un drapeau d' -debug-only=uncoalesced-analysis .
La commande suivante peut être utilisée pour exécuter l'analyse de l'indépendance de la taille d'un bloc sur un programme.
opt -load ../../../build/lib/LLVMBlockSizeInvarianceAnalysis.so - -instnamer -always-inline -interproc-bsize-invariance-analysis < gaussian-cuda-nvptx64-nvidia-cuda-sm_20.ll > /dev/null 2> gpuDranoResults.txt
Les résultats générés pour l'analyse d'accès à perception signalent tous les accès qui pourraient être potentiellement débordés dans chacun des noyaux GPU. Par exemple, voici les résultats de l'analyse de gaussian.cu .
Analysis Results:
Function: _Z4Fan1PfS_ii
Uncoalesced accesses: #2
-- gaussian.cu:295:59
-- gaussian.cu:295:61
Analysis Results:
Function: _Z4Fan2PfS_S_iii
Uncoalesced accesses: #4
-- gaussian.cu:312:38
-- gaussian.cu:312:35
-- gaussian.cu:312:35
-- gaussian.cu:317:23
Chaque élément de résultat pointe vers un accès potentiellement débordé dans le code source. Par exemple, l'accès à m_cuda à la ligne 295, la colonne 59 dans Gaussian.cu à la méthode Fan1() est non coalé.
De même, les résultats générés pour l'analyse de l'indépendance de la taille des blocs identifient tous les noyaux indépendants de la taille des blocs!
Rodinia est une suite de référence populaire de programmes GPU comprenant 22 programmes de différents domaines. Nous avons analysé la suite et trouvé 111 accès réels non coaloriques en utilisant une analyse statique. Pour reproduire les résultats, voici les étapes impliquées:
Mettez à jour la configuration CUDA et DRANO dans rodinia_3.1/common/make.config . Définissez CUDA_DIR et SDK_DIR avec NVIDIA Toolkit et SDK Chemins. Mettez à jour opt avec le chemin vers GPU Drano Binary LLVMUncoalescedAnalysis.so .
Allez dans le répertoire des références rodinia_3.1/cuda .
Compiler des références:
sh compile.sh
sh run-analysis.sh
L'analyse de chaque benchmark génère des résultats dans son dossier respectif dans les fichiers logiciels nommés log_<filename> .
./summarize-results.sh
Nvidia fournit un ensemble d'échantillons CUDA qui peuvent être utilisés pour diverses applications. Nous avons analysé la suite pour identifier les noyaux indépendants de taille de bloc dans les échantillons. Pour reproduire les résultats, les étapes sont:
Mettez à jour la variable HOME dans NVIDIA_CUDA-8.0_Samples/common/drano.mk au répertoire Root GPU Drano.
Installez OpenGL (requis pour compiler quelques repères). Sur Ubuntu, la commande suivante peut être utilisée:
sudo apt-get install freeglut3-dev
Accédez au répertoire NVIDIA_CUDA-8.0_Samples
Compiler des références:
sh compile.sh
sh run-analysis.sh
L'analyse de chaque benchmark génère des résultats dans son dossier respectif dans les fichiers logiciels nommés log_<filename> .
./summarize-bsize-independence.sh