Microsoft ajoute la prise en charge de la fonctionnalité collapse d'OpenMP dans Visual Studio

Par:
fredericmazue

lun, 12/02/2024 - 17:28

Microsoft améliore régulièrement la prise en charge d'OpenMP par le compilateur C/C++ de Visual Studio. Au début de ce mois, Microsoft a annoncé avoir corrigé plusieurs bugs et ajouté la prise en charge de la fonctionnalité collapse.

La fonctionnalité collapse d'OpenMP s'applique à un ensemble de boucle imbriquées, ou nid de boucles. L'ensemble du nid est alors considéré comme une boucle géante sur l'espace de boucle combiné et peut être divisé pour s'exécuter sur plusieurs threads, comme une seule boucle for. Soit cet exemple de nid de boucle rectangulaires :

void bar(float *a, int i, int j);
int jl, ju, il, iu;
void foo(float *a)
{
  int i, j;
  #pragma omp for collapse(2) private(i, j)
  for (i=il; i<=iu; ++i){
    for (j=jl; j<=ju; ++j)
      bar(a,i,j);
    }
}

Avec le pragma collapse, le compilateur génère un code similaire à celui-ci :

void bar(float *a, int i, int j);
int jl, ju, il, iu;
void foo(float *a)
{
  int i, j;
  kmp_uint64 ij, iju;

  bounds_info_t boundsNest[2] = { { loop_type_t::loop_type_int32,
                                    loop_type_t::loop_type_int32,
                                    comparison_t::comp_less_or_eq, 0,
                                    static_cast<kmp_uint64>(il), 0,
                                    static_cast<kmp_uint64>(iu), 0,
                                    static_cast<kmp_int64>(1), 0 },
                                  { loop_type_t::loop_type_int32,
                                    loop_type_t::loop_type_int32,
                                    comparison_t::comp_less_or_eq, 0,
                                    static_cast<kmp_uint64>(jl), 0,
                                    static_cast<kmp_uint64>(ju), 0,
                                    static_cast<kmp_int64>(1), 0 } };
  kmp_uint64 originalIVs[2];

  iju = __kmpc_process_loop_nest_rectang(
        nullptr, omp_get_thread_num(), /*in/out*/ boundsNest, 2);

  #pragma omp for private(i, j, ij)
  for (ij=0; ij<=iju; ++ij){µ
      __kmpc_calc_original_ivs_rectang(nullptr, ij,
                    boundsNest, /*out*/ originalIVs, 2);
      i = originalIVs[0];
      j = originalIVs[1];
      bar(a,i,j);
    }
}