Partager via


Démonstration : lancement du débogueur de cluster MPI dans Visual Studio 2010

Cette démonstration décrit la configuration et le lancement d'une session du débogueur de cluster MPI sur votre ordinateur local et sur un cluster Microsoft Windows HPC Server 2008. Cette démonstration inclut des procédures et un exemple de code pour la création d'une application à l'aide de MPI (Message Passing Interface) et des API (Application Programming Interface) OpenMP (Open Multi-Processing).

Dans ce guide :

  • Configuration requise pour l'utilisation du débogueur de cluster MPI

  • Création d'un projet d'exemple MPI C++ dans Visual Studio 2010

  • Configuration et lancement du débogueur de cluster MPI

  • Annexe : fichiers déployés par Visual Studio en plus des fichiers binaires d'application (et CRT, le cas échéant)

Configuration requise pour l'utilisation du débogueur de cluster MPI

  • Visual Studio 2010 Édition Professionnelle ou supérieure (notamment le débogueur distant) doit être installé sur votre ordinateur de développement.

  • Vous devez disposer d'autorisations administratives sur le cluster.

  • Visual Studio doit être en mesure d'accéder aux nœuds de calcul sur lesquels vous souhaitez exécuter la session de débogage. Vous pouvez bénéficier des accès nécessaires dans les cas suivants :

    • Vous développez votre application sur le nœud de tête du cluster ou sur un nœud de connexion dédié.

    • Vous utilisez un cluster dans lequel les nœuds de calcul sont connectés au réseau d'entreprise (topologie 2, 4 ou 5) et votre ordinateur de développement est associé au même domaine ou à un domaine disposant d'une relation d'approbation avec le domaine du cluster.

  • Pour envoyer votre application à un cluster HPC à partir d'un ordinateur client, Microsoft HPC Pack 2008 doit être installé.

  • Pour développer des programmes MPI à l'aide de l'interface MSMPI (Microsoft Message Passing Interface), le kit de développement Windows HPC Server 2008 doit être installé sur votre ordinateur de développement.

Création d'un projet d'exemple MPI C++ dans Visual Studio 2010

L'exemple de code présenté dans cette section s'applique à une application parallèle avoisinant la valeur de Pi à l'aide d'une simulation Monte Carlo.

Il est exécuté via 50 000 000 d'itérations sur chaque processus MPI. À chaque itération, l'exemple de code génère des nombres aléatoires dans l'intervalle [0,1] pour déterminer un ensemble de coordonnées x et y. L'ensemble de coordonnées est évalué pour déterminer si le point est situé sous la ligne x2 + y2 = 1. Si c'est le cas, la variable count est augmentée de 1. La valeur de count à partir de chaque processus MPI est ajoutée à la variable result. Le nombre total de points situés sous la ligne (result) est multiplié par quatre, puis divisé par le nombre total d'itérations pour avoisiner la valeur de Pi.

La procédure suivante inclut deux implémentations de la simulation Monte Carlo.

Création d'un exemple de projet

  1. Exécutez Visual Studio 2010.

  2. Créez une application console Win32 C++ nommée ParallelPI. Utilisez un projet sans en-tête pré-compilé.

    1. Dans le menu Fichier, pointez sur Nouveau, puis cliquez sur Projet.

    2. Dans la boîte de dialogue Nouveau projet, cliquez sur Modèles installés, puis sélectionnez Visual C++ (selon la configuration de Visual Studio, Visual C++ peut être situé sous le nœud Autres langages).

    3. Dans la liste des modèles, cliquez sur Application console Win32.

    4. Tapez le nom de projet suivant : ParallelPI.

    5. Cliquez sur OK. L'Assistant Application console Win32 s'affiche.

    6. Cliquez sur Suivant.

    7. Dans Paramètres de l'application, sous Options supplémentaires, désactivez la case à cocher En-tête précompilé.

    8. Cliquez sur Terminer pour fermer l'Assistant et créer le projet.

  3. Spécifiez d'autres propriétés pour le projet.

    1. Dans Explorateur de solutions, cliquez avec le bouton droit sur Parallel PI, puis cliquez sur Propriétés. La boîte de dialogue Pages de propriétés s'affiche.

    2. Développez Propriétés de configuration, puis sélectionnez Répertoires VC++.

      Dans Répertoires Include, placez le curseur au début de la liste qui s'affiche dans la zone de texte, puis spécifiez l'emplacement des fichiers d'en-têtes MS MPI C, suivi d'un point-virgule (;). Par exemple :

      C:\Program Files\Microsoft HPC Pack 2008 SDK\Include;
      
    3. Dans Répertoires de bibliothèques, placez le curseur au début de la liste qui s'affiche dans la zone de texte, puis spécifiez l'emplacement du fichier bibliothèque du kit de développement Microsoft HPC Pack 2008, suivi d'un point-virgule (;).

      Par exemple, si vous souhaitez créer et déboguer une application 32 bits :

      C:\Program Files\Microsoft HPC Pack 2008 SDK\Lib\i386;
      

      Si vous souhaitez créer et déboguer une application 64 bits :

      C:\Program Files\Microsoft HPC Pack 2008 SDK\Lib\amd64;
      
    4. Sous l'Éditeur de liens, sélectionnez Entrée.

      Dans la propriété Dépendances supplémentaires, placez le curseur au début de la liste qui apparaît dans la zone de texte, puis tapez :

      msmpi.lib;

    5. Si vous utilisez l'exemple de code avec OpenMP :

      Dans Propriétés de configuration, développez C/C++, puis sélectionnez Langage.

      Dans Prise en charge d'Open MP, sélectionnez Oui (/openmp) pour activer la prise en charge d'Open MP par le compilateur.

    6. Cliquez sur OK pour fermer les pages de propriétés.

  4. Dans le fichier source principal, sélectionnez l'ensemble du code, puis supprimez-le.

  5. Collez l'un des exemples de code suivants dans le fichier source vide. Le premier exemple utilise MPI et OpenMP, le deuxième MPI et PPL (Parallel Patterns Library).

    L'exemple de code suivant utilise MPI et OpenMP. La fonction ThrowDarts utilise une boucle parallèle OpenMP for pour utiliser le matériel multicœur s'il est disponible.

    // ParallelPI.cpp : Defines the entry point for the MPI application.
    //
    #include "mpi.h"
    #include "stdio.h"
    #include "stdlib.h"
    #include "limits.h"
    #include "omp.h"
    #include <random>
    
    int ThrowDarts(int iterations)
    {
    std::tr1::uniform_real<double> MyRandom;
    std::tr1::minstd_rand0 MyEngine;
    
    
    double RandMax = MyRandom.max();
    int count = 0;
    omp_lock_t MyOmpLock;
    
    omp_init_lock(&MyOmpLock);
    //Compute approximation of pi on each node
    #pragma omp parallel for
    for(int i = 0; i < iterations; ++i)
    {
    double x, y;
    x = MyRandom(MyEngine)/RandMax;
    y = MyRandom(MyEngine)/RandMax;
    
    if(x*x + y*y < 1.0)
    {
    omp_set_lock(&MyOmpLock);
    count++;
    omp_unset_lock(&MyOmpLock);
    }
    }
    
    omp_destroy_lock(&MyOmpLock);
    
    return count;
    }
    
    int main(int argc, char* argv[])
    {
    int rank;
    int size;
    int iterations;
    int count;
    int result;
    double time;
    MPI_Status s;
    
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    
    if(rank == 0)
    {
    //Rank 0 asks the number of iterations from the user.
    iterations = 50000000;
    if(argc > 1)
    {
    iterations = atoi(argv[1]);
    }
    printf("Executing %d iterations.\n", iterations);
    fflush(stdout);
    }
    //Broadcast the number of iterations to execute.
    if(rank == 0)
    {
    for(int i = 1; i < size; ++i)
    {
    MPI_Ssend(&iterations, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
    }
    }
    else
    {
    MPI_Recv(&iterations, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &s);
    }
    
    //MPI_Bcast(&iterations, 1, MPI_INT, 0, MPI_COMM_WORLD);
    
    count = ThrowDarts(iterations);
    
    //Gather and sum results
    if(rank != 0)
    {
    MPI_Ssend(&count, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
    }
    else
    {
    for(int i = 1; i < size; ++i)
    {
    int TempCount = 0;
    MPI_Recv(&TempCount, 1, MPI_INT, i, 0, MPI_COMM_WORLD, &s);
    count += TempCount;
    }
    }
    result = count;
    
    //MPI_Reduce(&count, &result, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
    
    if(rank == 0)
    {
    printf("The value of PI is approximated to be: %16f", 4*((float)result/(float)(iterations*size)));
    }
    
    MPI_Barrier(MPI_COMM_WORLD);
    
    MPI_Finalize();
    return 0;
    }
    

     

    L'exemple de code suivant utilise PPL (Parallel Patterns Library) plutôt qu'OpenMP, et les opérations collectives MPI plutôt que les opérations point à point :

     

    // ParallelPI.cpp : Defines the entry point for the MPI application.
    //
    #include "mpi.h"
    #include "stdio.h"
    #include "stdlib.h"
    #include "limits.h"
    #include <ppl.h>
    #include <random>
    #include <time.h>
    
    using namespace Concurrency;
    
    int ThrowDarts(int iterations)
    {
    
    combinable<int> count;
    
    int result = 0;
    
    
    parallel_for(0, iterations, [&](int i){
    
    std::tr1::uniform_real<double> MyRandom;
    double RandMax = MyRandom.max();
    std::tr1::minstd_rand0 MyEngine;
    double x, y;
    
    MyEngine.seed((unsigned int)time(NULL));
    
    x = MyRandom(MyEngine)/RandMax;
    y = MyRandom(MyEngine)/RandMax;
    
    if(x*x + y*y < 1.0)
    {
    count.local() += 1;
    }
    });
    
    result = count.combine([](int left, int right) { return left + right; });
    
    return result;
    }
    
    void main(int argc, char* argv[])
    {
    int rank;
    int size;
    int iterations;
    int count;
    int result;
    
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    
    if(rank == 0)
    {
    //Rank 0 reads the number of iterations from the command line.
    //50M iterations is the default.
    iterations = 50000000;
    if(argc > 1)
    {
    iterations = atoi(argv[argc-1]);
    }
    printf("Executing %d iterations on %d nodes.\n", iterations, size);
    fflush(stdout);
    }
    //Broadcast the number of iterations to execute.
    MPI_Bcast(&iterations, 1, MPI_INT, 0, MPI_COMM_WORLD);
    
    count = ThrowDarts(iterations);
    
    //Gather and sum results
    MPI_Reduce(&count, &result, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
    
    if(rank == 0)
    {
    printf("The value of PI is approximated to be: %16f", 4*((double)result/(double)(iterations*size)));
    }
    
    MPI_Barrier(MPI_COMM_WORLD);
    
    MPI_Finalize();
    
    }
    
  6. Dans le menu Fichier, cliquez sur Enregistrer tout.

  7. Dans le menu Générer, cliquez sur Régénérer la solution.

Configuration et lancement du débogueur de cluster MPI

Après avoir créé votre application, vous êtes prêt à configurer et lancer le débogueur. Cette section décrit les options de débogage :

  • Débogage d'un processus MPI unique sur l'ordinateur local

  • Débogage de plusieurs processus MPI sur l'ordinateur local

  • Débogage d'un ou plusieurs processus MPI sur un cluster

Ee441265.note(fr-fr,VS.100).gifRemarque :
Vous ne pouvez pas lancer le débogueur de cluster MPI sans effectuer un débogage. Le fait d'appuyer sur Ctrl+F5 (ou de sélectionner Exécuter sans débogage dans le menu Débogage) lance également le débogage.

Débogage d'un processus MPI unique sur l'ordinateur local

Pour effectuer un débogage sur l'ordinateur local à l'aide d'un seul processus MPI, utilisez le processus que vous utiliseriez pour déboguer une autre application. Définissez un point d'arrêt à l'emplacement souhaité de votre programme, puis appuyez sur F5 pour lancer le débogueur.

Les programmes MPI communiquent via IP sur des ports. Au premier lancement d'un programme MPI, le pare-feu risque d'afficher un avertissement de sécurité indiquant qu'un port est en cours d'ouverture. Lisez ce message et assurez-vous de comprendre les modifications apportées à votre système. Vous devez débloquer le pare-feu pour poursuivre le débogage sur l'ordinateur local.

Débogage de plusieurs processus MPI sur l'ordinateur local

La procédure suivante décrit comment lancer une session de débogage local pour ParallelPI.

Pour lancer le débogueur de cluster MPI avec quatre processus MPI exécutés sur l'ordinateur local

  1. Dans Explorateur de solutions, cliquez avec le bouton droit sur Parallel PI, puis cliquez sur Propriétés. La boîte de dialogue Pages de propriétés s'affiche.

  2. Développez le nœud Propriétés de configuration, puis sélectionnez Débogage.

  3. Sous Débogueur à lancer, sélectionnez Débogueur de cluster MPI.

  4. Dans Environnement d'exécution, sélectionnez Modifier le nœud Hpc dans la liste déroulante. La boîte de dialogue Sélecteur de nœuds s'affiche.

  5. Dans la liste déroulante Nœud de tête, sélectionnez localhost.

  6. Dans Nombre de processus, sélectionnez 4.

  7. Cliquez sur OK pour enregistrer les modifications et fermer la boîte de dialogue Sélecteur de nœuds.

  8. ParallelPI accepte un seul argument qui détermine le nombre d'itérations à exécuter. Par défaut, il est défini sur 50 000 000. Pour la session de débogage local, réduisez le nombre d'itérations à 5 000 comme suit :

    Dans Arguments d'application, tapez 5000.

  9. Cliquez sur OK pour enregistrer les modifications et fermer les pages de propriétés.

  10. Définissez un point d'arrêt dans le corps de la parallèle for pour la boucle.

  11. Appuyez sur F5 pour lancer le débogueur.

  12. Cinq fenêtres de console doivent s'afficher : une fenêtre cmd.exe et quatre fenêtres ParallelPI.exe (une pour chaque processus lancé). La fenêtre de console correspondant au processus de rang 0 indique le nombre d'itérations et le calcul approximatif de Pi.

  13. Dans le menu Déboguer, cliquez sur Windows, puis sur Processus.

  14. Configurez le processus actif du débogage en double-cliquant sur un processus dans la fenêtre Processus.

Ee441265.note(fr-fr,VS.100).gifRemarque :
Lorsque vous déboguez plusieurs processus, un point d'arrêt affecte par défaut tous les processus en cours de débogage. Pour éviter l'arrêt des processus à des endroits non prévus, désactivez l'option Arrêter tous les processus lorsqu'un processus s'arrête. (Dans le menu Outils, cliquez sur Options, puis sélectionnez Débogage). Pour plus d'informations sur la modification du comportement des arrêts, voir la rubrique Comment : arrêter l'exécution.

Débogage d'un ou plusieurs processus MPI sur un cluster

Lorsque vous lancez le débogueur MPI sur un cluster, celui-ci envoie votre application au cluster en tant que travail. Les fichiers d'exécution Visual C correspondant à votre projet (x86 ou x64, débogage ou version finale) doivent être situés dans le répertoire de travail sur les nœuds de calcul. Si les fichiers d'exécution adéquats ne sont pas déjà situés sur les nœuds de calcul, vous devez les inclure dans le déploiement du débogueur en spécifiant la propriété Fichiers supplémentaires à déployer. La procédure suivante décrit notamment le déploiement des DLL d'exécution du débogage OpenMP. Par défaut, le fichier de bibliothèque CRT (C Runtime) est déployé lorsque vous lancez le débogueur de cluster MPI. Si les fichiers d'exécution adéquats sont manquants, des erreurs côte à côte apparaissent lorsque vous tentez d'exécuter votre application. Si le fichier d'exécution OpenMP est manquant, les points d'arrêt ne sont pas atteints.

Lancement du débogueur MPI sur un cluster

  1. Dans Explorateur de solutions, cliquez avec le bouton droit sur Parallel PI, puis cliquez sur Propriétés. La boîte de dialogue Pages de propriétés s'affiche.

  2. Développez le nœud Propriétés de configuration, puis sélectionnez Débogage.

  3. Sous Débogueur à lancer, sélectionnez Débogueur de cluster MPI.

  4. Dans Environnement d'exécution, sélectionnez Modifier le nœud Hpc dans la liste déroulante. La boîte de dialogue Sélecteur de nœuds s'affiche.

  5. Dans la liste déroulante Nœud de tête, sélectionnez le nom du nœud de tête du cluster à utiliser.

    La liste des nœuds de tête est renseignée à partir d'Active Directory sur le contrôleur de domaine. Seuls les clusters de votre domaine apparaissent dans la liste. Si vous ne voyez pas le nœud de tête, tapez le nom ou l'adresse IPv4 de celui-ci dans le champ de propriété.

  6. Dans Nombre de processus, sélectionnez 4.

  7. Dans Planifier un processus par, sélectionnez la façon dont vous souhaitez allouer vos processus. Vous pouvez allouer un processus par Cœur, Socket ou Nœud.

  8. Cliquez sur OK pour enregistrer les modifications et fermer la boîte de dialogue Sélecteur de nœuds.

  9. Dans Répertoire de déploiement, spécifiez un répertoire partagé sur le nœud de tête. Si le répertoire de déploiement n'existe pas et si vous disposez des autorisations en écriture dans le répertoire racine spécifié, le répertoire de déploiement est créé automatiquement.

    La ressource partagée du répertoire CcpSpoolDir est créée lorsque le pack HPC 2008 est installé sur le nœud de tête. Par exemple, tapez ce qui suit, où <myHeadNode> est le nom du cluster utilisé :

    \\<myHeadNode>\CcpSpoolDir\

  10. Dans Répertoire de travail, spécifiez un répertoire de travail local sur chaque nœud de calcul. Par exemple, tapez ce qui suit, où <myUserName> est votre nom d'utilisateur :

    C:\Users\<myUserName>\ParallelPI

  11. Si vous utilisez un exemple de code avec OpenMP, ajoutez le fichier DLL d'exécution du débogage OpenMP (Microsoft.VC100.DebugOpenMP\vcomp100d.dll) :

    1. Dans Fichiers supplémentaires à déployer, sélectionnez <Modifier le fichier…>. La boîte de dialogue Sélecteur de fichiers et de dossiers s'affiche.

    2. Cliquez sur Ajouter un fichier, accédez au fichier Microsoft.VC100.DebugOpenMP\vcomp100d.dll, sélectionnez-le, puis cliquez sur Ouvrir.

      Par exemple, sur les éditions x86, l'emplacement par défaut sur une édition 64 bits du système d'exploitation Windows Server 2008 est :

      C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC100.DebugOpenMP\ vcomp100d.dll

    3. Cliquez sur OK pour ajouter le fichier et fermer la boîte de dialogue Sélecteur de fichiers et de dossiers.

  12. Cliquez sur OK pour enregistrer les modifications et fermer les pages de propriétés.

  13. Définissez un point d'arrêt dans le corps de la parallèle for pour la boucle.

  14. Appuyez sur F5 pour lancer le débogueur.

  15. Lorsque vous envoyez un travail au cluster, vous êtes invité à entrer votre mot de passe pour vous connecter à celui-ci. Tapez votre mot de passe et appuyez sur ENTRÉE.

  16. Une fois le débogueur lancé, consultez la fenêtre de processus pour vérifier le positionnement des processus. Pour chaque processus, consultez la colonne Qualificateur de transport pour afficher le nœud de calcul sur lequel le processus est en cours d'exécution.

Annexe : fichiers déployés par Visual Studio en plus des fichiers binaires d'application (et CRT, le cas échéant)

  • DebuggerProxy.dll

  • DebuggerProxy.dll.manifest

  • Delete_from_workdir.bat : script qui permet de supprimer les fichiers déployés

  • Deploy_to_workdir.bat : script qui permet de copier les fichiers du répertoire de déploiement vers le répertoire de travail

  • dbghelp.dll

  • mcee.dll

  • Mpishim.bat : script qui permet de lancer le débogueur distant

  • Mpishim.exe : programme qui gère les communications entre l'IDE et Msvsmon.exe

  • Msvsmon.exe : débogueur distant

  • Msvsmon.exe.config

  • PfxTaskProvider.dll

  • symsrv.dll

  • symsrv.yes

  • vbdebug.dll

  • 1036\msdbgui.dll

  • 1036\vbdebugui.dll

Voir aussi

Concepts

Propriétés de configuration du débogueur de cluster MPI
Débogage d'applications MPI sur un cluster HPC

Autres ressources

Étapes du débogueur
mpiexec Command Reference