Partager via


Comment : convertir une boucle OpenMP qui a recours à la gestion des exceptions pour utiliser le runtime d'accès concurrentiel

Cet exemple montre comment convertir un parallèleOpenMP pour la boucle qui effectue la gestion des exceptions pour utiliser le mécanisme de gestion des exceptions du runtime d’accès concurrentiel.

Dans OpenMP, une exception levée dans une région parallèle doit être interceptée et gérée dans la même région par le même thread. Une exception qui échappe à la région parallèle est interceptée par le gestionnaire d’exceptions non géré, qui met fin au processus par défaut.

Dans le runtime d’accès concurrentiel, lorsque vous lèvez une exception dans le corps d’une fonction de travail que vous passez à un groupe de tâches tel qu’une concurrence ::task_group ou concurrency ::structured_task_group objet, ou à un algorithme parallèle tel que concurrency ::p arallel_for, le runtime stocke cette exception et le marshale dans le contexte qui attend que le groupe de tâches ou l’algorithme se termine. Pour les groupes de tâches, le contexte d’attente est le contexte qui appelle concurrency ::task_group ::wait, concurrency ::structured_task_group ::wait, concurrency ::task_group ::run_and_wait ou concurrency ::structured_task_group ::run_and_wait. Pour un algorithme parallèle, le contexte d’attente est le contexte qui a appelé cet algorithme. Le runtime arrête également toutes les tâches actives qui se trouvent dans le groupe de tâches, y compris celles des groupes de tâches enfants, et ignore toutes les tâches qui n’ont pas encore démarré.

Exemple

Cet exemple montre comment gérer les exceptions dans une région OpenMP parallel et dans un appel à parallel_for. La do_work fonction effectue une demande d’allocation de mémoire qui ne réussit pas et lève donc une exception de type std ::bad_alloc. Dans la version qui utilise OpenMP, le thread qui lève l’exception doit également l’intercepter. En d’autres termes, chaque itération d’une boucle parallèle OpenMP doit gérer l’exception. Dans la version qui utilise le runtime d’accès concurrentiel, le thread principal intercepte une exception levée par un autre thread.

// concrt-omp-exceptions.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <new>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

// Demonstrates a function that performs a memory allocation request 
// that does not succeed.
void do_work(int)
{
   // The following memory allocation causes this function to 
   // throw std::bad_alloc.
   char* ptr = new char[(~unsigned int((int)0)/2) - 1];

   // TODO: Assuming that the allocation succeeds, perform some work 
   // and free the allocated memory.

   delete[] ptr;
}

// Demonstrates an OpenMP parallel loop that performs exception handling.
void omp_exception_handling()
{
   #pragma omp parallel for 
      for(int i = 0; i < 10; i++) 
      {
         try {
            // Perform a unit of work.
            do_work(i);
         }
         catch (exception const& e) {
            // Print the error to the console.
            wstringstream ss;
            ss << L"An error of type '" << typeid(e).name() 
               << L"' occurred." << endl;
            wcout << ss.str();
         }
      }
}

// Demonstrates an Concurrency Runtime parallel loop that performs exception handling.
void concrt_exception_handling()
{
   try {
      parallel_for(0, 10, [](int i) 
      {
         // Perform a unit of work.
         do_work(i);
      });
   }
   catch (exception const& e) {
      // Print the error to the console.
      wcout << L"An error of type '" << typeid(e).name() 
            << L"' occurred." << endl;
   }
}

int wmain()
{
   wcout << L"Using OpenMP..." << endl;
   omp_exception_handling();

   wcout << L"Using the Concurrency Runtime..." << endl;
   concrt_exception_handling();
}

Cet exemple produit la sortie suivante.

Using OpenMP...
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
Using the Concurrency Runtime...
An error of type 'class std::bad_alloc' occurred.

Dans la version de cet exemple qui utilise OpenMP, l’exception se produit et est gérée par chaque itération de boucle. Dans la version qui utilise le runtime d’accès concurrentiel, le runtime stocke l’exception, arrête toutes les tâches actives, ignore toutes les tâches qui n’ont pas encore démarré et marshale l’exception dans le contexte qui appelle parallel_for.

Si vous avez besoin que la version qui utilise OpenMP se termine après l’exception, vous pouvez utiliser un indicateur booléen pour signaler à d’autres itérations de boucle que l’erreur s’est produite. Comme dans l’exemple de la rubrique Procédure : convertir une boucle OpenMP qui utilise l’annulation pour utiliser le runtime d’accès concurrentiel, les itérations de boucle suivantes ne font rien si l’indicateur est défini. À l’inverse, si vous avez besoin que la boucle qui utilise le runtime d’accès concurrentiel se poursuit une fois l’exception effectuée, gérez l’exception dans le corps de la boucle parallèle elle-même.

Les autres composants du runtime d’accès concurrentiel, tels que les agents asynchrones et les tâches légères, ne transportent pas d’exceptions. Au lieu de cela, les exceptions non gérées sont interceptées par le gestionnaire d’exceptions non gérés, ce qui met fin au processus par défaut. Si vous souhaitez en savoir plus, veuillez consulter la rubrique Gestion des exceptions.

Pour plus d’informations sur parallel_for et d’autres algorithmes parallèles, consultez Algorithmes parallèles.

Compilation du code

Copiez l’exemple de code et collez-le dans un projet Visual Studio, ou collez-le dans un fichier nommé concrt-omp-exceptions.cpp , puis exécutez la commande suivante dans une fenêtre d’invite de commandes Visual Studio.

cl.exe /EHsc /openmp concrt-omp-exceptions.cpp

Voir aussi

Migration d’OpenMP au runtime d’accès concurrentiel
Gestion des exceptions
Algorithmes parallèles