Tutorial: Iniciar el Depurador de clúster MPI en Visual Studio 2010

En este tutorial, aprenderá a configurar e iniciar una sesión del Depurador de clúster MPI en su equipo local y en un clúster de Microsoft Windows HPC Server 2008. Este tutorial incluye los pasos y el código de ejemplo necesarios para crear una aplicación que utilice la Interfaz de paso de mensajes (MPI) y las interfaces de programación de aplicaciones (API) de multiprocesamiento abierto (OpenMP).

En esta guía:

  • Requisitos de uso del Depurador de clúster MPI

  • Crear un proyecto de muestra de MPI en C++ en Visual Studio 2010

  • Configurar e iniciar el Depurador de clúster MPI

  • Apéndice: Archivos implementados con Visual Studio además de los archivos binarios de la aplicación (y CRT, si se solicita)

Requisitos de uso del Depurador de clúster MPI

  • Debe tener instalado Visual Studio 2010 Professional Edition o posterior (incluido el depurador remoto) en el equipo de desarrollo.

  • Debe contar con permisos de administrador en el clúster.

  • Visual Studio debe tener acceso a los nodos de computación en los que va a ejecutar la sesión de depuración. Los casos siguientes proporcionan el acceso necesario:

    • Va a desarrollar la aplicación en el nodo de encabezado del clúster o en un nodo de inicio de sesión dedicado.

    • Va a utilizar un clúster cuyos nodos de computación se encuentran conectados a la red de la empresa (Topología 2, 4 o 5) y el equipo de desarrollo está unido al mismo dominio o a un dominio que tiene una relación de confianza con el dominio del clúster.

  • Para enviar la aplicación a un clúster de HPC desde un equipo cliente, debe tener instalado Microsoft HPC Pack 2008.

  • Para crear programas de MPI mediante la Interfaz de paso de mensajes de Microsoft, es necesario tener instalado Windows HPC Server 2008 SDK en el equipo de desarrollo.

Crear un proyecto de muestra de MPI en C++ en Visual Studio 2010

El código de muestra de esta sección es para una aplicación paralela que proporciona una aproximación al valor de pi mediante una simulación Monte Carlo.

El código de muestra se ejecuta en 50.000.000 iteraciones en cada proceso de MPI. En cada iteración, el código de muestra genera números aleatorios en el intervalo [0,1] para determinar un conjunto de coordenadas de x y de y. El conjunto de coordenadas se evalúa para determinar si el punto se encuentra dentro de la línea x2 + y2 = 1. Si el punto cae debajo de la línea, la variable count aumentará en uno. El valor de count de cada proceso de MPI se suma en la variable result. El número total de puntos que se encuentran dentro de la línea (result) se multiplica por cuatro y, a continuación, se divide por el número total de iteraciones para obtener una aproximación del valor de pi.

El siguiente procedimiento incluye dos implementaciones de la simulación Monte Carlo.

  • La primera muestra usa MPI y OpenMP. Para obtener más información acerca de OpenMP, consulte OpenMP in Visual C++.

  • La segunda muestra usa MPI y Parallel Patterns Library (PPL). Para obtener más información acerca de PPL, consulte Parallel Patterns Library (PLL).

Para crear el proyecto de muestra

  1. Ejecute Visual Studio 2010.

  2. Cree una nueva aplicación de consola Win32 de Visual C++ con el nombre PI paralela. Utilice un proyecto sin encabezados precompilados.

    1. En el menú Archivo, señale Nuevo y, a continuación, haga clic en Proyecto.

    2. En el cuadro de diálogo Nuevo proyecto, haga clic en Plantillas instaladas y, a continuación, seleccione Visual C++. (En función de cómo haya configurado Visual Studio, Visual C++ puede encontrarse bajo el nodo Otros lenguajes.)

    3. En la lista de plantillas, haga clic en Aplicación de consola Win32.

    4. Para el nombre del proyecto, escriba: ParallelPI.

    5. Haga clic en Aceptar. Se abrirá el Asistente para la Aplicación de consola Win32.

    6. Haga clic en Siguiente.

    7. En Configuración de la aplicación, debajo de Opciones adicionales, desactive la casilla de verificación Encabezado precompilado.

    8. Haga clic en Finalizar para cerrar el asistente y crear el proyecto.

  3. Especifique las propiedades adicionales del proyecto.

    1. En Explorador de soluciones, haga clic con el botón secundario en PI paralela y, a continuación, en Propiedades. Se abrirá el cuadro de diálogo Páginas de propiedades.

    2. Expanda Propiedades de configuración y, a continuación, seleccione Directorios de VC++.

      En Incluir directorios, coloque el cursor al principio de la lista que aparece en el cuadro de texto, a continuación, especifique la ubicación de los archivos de encabezado MPI C, seguido de punto y coma (;). Por ejemplo:

      C:\Program Files\Microsoft HPC Pack 2008 SDK\Include;
      
    3. En Directorios de archivos de bibliotecas, coloque el cursor al principio de la lista que aparece en el cuadro de texto, a continuación, especifique la ubicación del archivo de biblioteca de Microsoft HPC Pack 2008 SDK, seguido de punto y coma (;).

      Por ejemplo, si desea crear y depurar una aplicación de 32 bits:

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

      Si desea crear y depurar una aplicación de 64 bits:

      C:\Program Files\Microsoft HPC Pack 2008 SDK\Lib\amd64;
      
    4. Debajo de Vinculador, seleccione Entrada.

      En Dependencias adicionales, coloque el cursor al comienzo de la lista que aparece en el cuadro de texto y, a continuación, escriba:

      msmpi.lib;

    5. Si va a usar el código de muestra con OpenMP:

      En Propiedades de configuración, expanda C/C++ y, a continuación, seleccione Idioma.

      En Compatibilidad con OpenMP, seleccione Sí (/openmp) para habilitar la compatibilidad con el compilador para OpenMP.

    6. Haga clic en Aceptar para cerrar la página de propiedades.

  4. En el archivo de origen principal, seleccione todo el código y elimínelo.

  5. Pegue uno de los siguientes códigos de muestra en el archivo de origen vacío. La primera muestra utiliza MPI y OpenMP y la segunda MPI y Parallel Patterns Library (PPL).

    El siguiente código de muestra usa MPI y OpenMP. La función ThrowDarts usa un bucle OpenMP paralelo for para utilizar el hardware multinúcleo si 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;
    }
    

     

    El siguiente código de muestra utiliza Parallel Patterns Library (PPL), en lugar de OpenMP, y usa las operaciones colectivas de MPI en lugar de operaciones punto a punto.

     

    // 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. En el menú Archivo, haga clic en Guardar todo.

  7. En el menú Generar, haga clic en Volver a generar solución.

Configurar e iniciar el Depurador de clúster MPI

Tras crear su aplicación, ya está listo para configurar e iniciar el depurador. En esta sección se describen tres opciones de depuración:

  • Depurar un proceso de MPI en el equipo local

  • Depurar un proceso de MPI múltiple en el equipo local

  • Depurar uno o varios procesos de MPI de un clúster

Nota

En el Depurador de clúster MPI, no puede empezar sin depurar. Al pulsar Ctrl+F5 (o Iniciar sin depurar en el menú Depurar) también se inicia la depuración.

Depurar un proceso de MPI en el equipo local

Para depurar en el equipo local a través de un sólo proceso de MPI, utilice el mismo proceso que emplearía para depurar cualquier otra aplicación. Establezca un punto de interrupción en la ubicación deseada del programa y presione F5 para iniciar el depurador.

Los programas de MPI se comunican a través las IP de los puertos. La primera vez que inicie un programa de MPI, es posible que aparezca una advertencia de seguridad del firewall que indica que se va a abrir un puerto. Lea el mensaje de advertencia y asegúrese de entender los cambios que va a realizar en el sistema. Debe desbloquear el firewall para continuar la depuración en el equipo local.

Depurar un proceso de MPI múltiple en el equipo local

El siguiente procedimiento describe cómo iniciar una sesión de depuración local para ParallelPI.

Para iniciar el Depurador de clúster MPI con cuatro procesos MPI en ejecución en el equipo local

  1. En Explorador de soluciones, haga clic con el botón secundario en ParallelPI y, a continuación, en Propiedades. Se abrirá el cuadro de diálogo Páginas de propiedades.

  2. Expanda Propiedades de configuración y, a continuación, seleccione Depuración.

  3. Debajo de Depurador para iniciar, seleccione Depurador de clúster MPI.

  4. En Entorno de ejecución, seleccione Editar nodo HPC en la lista desplegable. Se abrirá el cuadro de diálogo Selector de nodos.

  5. En la lista desplegable Nodo de encabezado, seleccione localhost.

  6. En Número de procesos, seleccione 4.

  7. Haga clic en Aceptar para guardar los cambios y cerrar el cuadro de diálogo Selector de nodos.

  8. ParallelPI acepta un argumento que determina el número de iteraciones que se van a ejecutar. El valor predeterminado es 50.000.000. Para la sesión de depuración local, reduzca las iteraciones a 5.000 como se describe a continuación:

    En Argumentos de la aplicación, escriba 5000.

  9. Haga clic en Aceptar para guardar los cambios y cerrar Páginas de propiedades.

  10. Establezca un punto de interrupción en el cuerpo del bucle paralelo for.

  11. Presione F5 para iniciar el depurador.

  12. Deberían aparecer cinco ventanas de consola: una ventana cmd.exe y cuatro ventanas ParallelPI.exe (una para cada proceso que haya iniciado). La ventana de consola que corresponde al proceso de rango 0 indica el número de iteraciones y la aproximación calculada de pi.

  13. En el menú Depurar, haga clic en Ventanas y, a continuación, en Procesos.

  14. Para establecer el proceso activo que desea depurar, haga doble clic en un proceso de la ventana Procesos.

Nota

Al depurar procesos múltiples, un punto de interrupción afectará a todos los procesos objeto de la depuración de forma predeterminada. Para evitar la interrupción de los procesos en ubicaciones no deseadas, anule la selección de la opción Interrumpir todos los procesos cuando se interrumpa uno. (En el menú Herramientas, haga clic en Opciones y, a continuación, seleccione Depurar). Para obtener más información acerca de cómo cambiar un comportamiento de interrupción, consulte Cómo: Interrumpir la ejecución.

Depurar uno o varios procesos MPI de un clúster

Cuando se inicia el Depurador de MPI en un clúster, éste envía la aplicación a dicho clúster como un trabajo. Los tiempos de ejecución de Visual C que coincidan con el proyecto (x86 o x64, depuración o liberación) deben encontrarse en el directorio de los nodos de computación. Si los tiempos de ejecución correctos no se encuentran aún en los nodos de computación, será necesario incluirlos en la implementación del depurador mediante la especificación de la propiedad Archivos adicionales para implementar. El procedimiento siguiente incluye un paso para implementar la DLL de tiempos de ejecución de depuración de OpenMP. De forma predeterminada, la biblioteca de tiempo de ejecución de C (CRT) se implementa al iniciar el Depurador de clúster MPI. Si no están presentes los tiempos de ejecución correctos, se mostrarán errores en paralelo al intentar ejecutar la aplicación. Si el tiempo de ejecución de OpenMP no está incluido, no se ejecutarán los puntos de interrupción.

Para iniciar el Depurador de MPI en un clúster

  1. En Explorador de soluciones, haga clic con el botón secundario en PI paralela y, a continuación, en Propiedades. Se abrirá el cuadro de diálogo Páginas de propiedades.

  2. Expanda Propiedades de configuración y, a continuación, seleccione Depuración.

  3. Debajo de Depurador para iniciar, seleccione Depurador de clúster MPI.

  4. En Entorno de ejecución, seleccione Editar nodo HPC en la lista desplegable. Se abrirá el cuadro de diálogo Selector de nodos.

  5. En la lista desplegable Nodo de encabezado, seleccione el nombre del nodo de encabezado para el clúster que desee utilizar.

    La lista de nodos de encabezado se llena con el controlador de dominio de Active Directory. Tan sólo aparecerán en la lista los clústeres de su dominio. Si no se muestra el nodo de encabezado, escriba el nombre o la dirección IPv4 de dicho nodo en el campo de propiedades.

  6. En Número de procesos, seleccione 4.

  7. En Programar un proceso por, seleccione cómo asignar los procesos. Puede asignar un proceso por Núcleo, Zócalo o Nodo.

  8. Haga clic en Aceptar para guardar los cambios y cerrar el cuadro de diálogo Selector de nodos.

  9. En Directorio de implementación, especifique un directorio compartido en el nodo de encabezado. Si el directorio de implementación no existe y dispone de permisos de escritura en el directorio raíz especificado, el directorio de implementación se crea automáticamente.

    El recurso compartido de directorio CcpSpoolDir se crea al instalar el paquete HPC Pack 2008 en el nodo de encabezado. Por ejemplo, escriba lo siguiente, donde <myHeadNode> es el nombre del clúster que va a utilizar:

    \\<myHeadNode>\CcpSpoolDir\

  10. En Directorio de trabajo, especifique un directorio de trabajo local en cada nodo de computación. Por ejemplo, escriba lo siguiente, donde <myUserName> es su nombre de usuario:

    C:\Users\<myUserName>\ParallelPI

  11. Si va a utilizar el código de muestra con OpenMP, agregue el archivo de DLL de tiempo de ejecución de depuración de OpenMP (Microsoft.VC100.DebugOpenMP\vcomp100d.dll):

    1. En Archivos adicionales para implementar, seleccione <Editar archivo…>. Se abrirá el cuadro de diálogo Selector de archivos y carpetas.

    2. Haga clic en Agregar archivo, vaya a Microsoft.VC100.DebugOpenMP\vcomp100d.dll, seleccione el archivo y, a continuación, haga clic en Abrir.

      Por ejemplo, en un equipo basado en x86, la ubicación predeterminada en una edición de 64 bits del sistema operativo de Windows Server 2008 es:

      C:\Archivos de programa (x86)\Microsoft Visual Studio 10.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC100.DebugOpenMP\ vcomp100d.dll

    3. Haga clic en Aceptar para agregar el archivo y cerrar el cuadro de diálogo Selector de archivos y carpetas.

  12. Haga clic en Aceptar para guardar los cambios y cerrar Páginas de propiedades.

  13. Establezca un punto de interrupción en el cuerpo del bucle paralelo for.

  14. Presione F5 para iniciar el depurador.

  15. Como va a enviar un trabajo al clúster, se le solicitará que introduzca su contraseña para conectar con el clúster. Escriba su contraseña y presione ENTRAR.

  16. Una vez iniciado el depurador, observe la ventana del proceso para comprobar la colocación de los procesos. Para cada proceso, compruebe la columna Calificador de transporte para ver el nodo de computación en el que se está ejecutando el proceso.

Apéndice: Archivos implementados con Visual Studio además de los archivos binarios de la aplicación (y CRT, si se solicita)

  • DebuggerProxy.dll

  • DebuggerProxy.dll.manifest

  • Delete_from_workdir.bat: Una secuencia de comandos para eliminar los archivos implementados

  • Delete_from_workdir.bat: Una secuencia de comandos para copiar archivos del directorio de implementación al directorio de trabajo

  • dbghelp.dll

  • mcee.dll

  • Mpishim.bat: Una secuencia de comandos para iniciar el depurador remoto

  • Mpishim.exe: Un programa que organiza la comunicación entre el IDE y MSVSMon.exe

  • Msvsmon.exe: El depurador remoto

  • Msvsmon.exe.config

  • PfxTaskProvider.dll

  • symsrv.dll

  • symsrv.yes

  • vbdebug.dll

  • 3082\msdbgui.dll

  • 3082\vbdebugui.dll

Consulte también

Conceptos

Propiedades de configuración para el Depurador de clúster MPI
Cómo depurar aplicaciones de MPI en un clúster HPC

Otros recursos

Plan del depurador
mpiexec Command Reference