2 votes

Allouer de la mémoire par thread dans une boucle parallel_for

Je dispose à l'origine d'une boucle mono-thread qui itère sur tous les pixels d'une image et peut effectuer diverses opérations sur les données.

La bibliothèque que j'utilise dicte que la récupération des pixels d'une image doit se faire ligne par ligne. Pour ce faire, j'alloue dynamiquement un bloc de mémoire pouvant contenir une rangée de pixels (BMM_Color_fl est une structure contenant les données RGBA d'un pixel sous forme de quatre valeurs flottantes, et GetLinearPixels() copie une rangée de pixels depuis une bitmap dans un tableau BMM_Color_fl.)

BMM_Color_fl* ligne = (BMM_Color_fl*)malloc(largeur * sizeof(BMM_Color_fl));
for (int y = 0; y < hauteur; y++)
{   
    bmp->GetLinearPixels(0, y, largeur, ligne); //Copie des données de la rangée Y depuis la bitmap dans la ligne.
    BMM_Color_fl* pixel = ligne; //Récupérer le premier pixel de la ligne.
    for (int x = 0; x < largeur; x++, pixel++) // Pour chaque pixel dans la rangée...
    {
        //Faire quelque chose avec un pixel.
    }
}
free(ligne);

Jusqu'ici tout va bien!

Dans le but de réduire le temps d'exécution de cette boucle, j'ai écrit une version concurrente utilisant parallel_for, qui ressemble à ceci :

parallel_for(0, hauteur, [&](int y)
{   
    BMM_Color_fl* ligne = (BMM_Color_fl*)malloc(largeur * sizeof(BMM_Color_fl));
    bmp->GetLinearPixels(0, y, largeur, ligne);
    BMM_Color_fl* pixel = ligne;
    for (int x = 0; x < largeur; x++, pixel++)
    {
        //Faire quelque chose avec un pixel.
    }
    free(ligne);
});

Alors que la boucle multithread est déjà plus rapide que l'originale, je réalise qu'il est impossible pour tous les threads d'utiliser le même bloc de mémoire, donc actuellement j'alloue et libère la mémoire à chaque itération de la boucle, ce qui est évidemment gaspilleur car il n'y aura jamais plus de threads que d'itérations de boucle.

Ma question est la suivante : comment puis-je faire en sorte que chaque thread alloue exactement un tampon de ligne et l'utilise de manière répétée (et idéalement, le libère à la fin) ?

  • Je dois préciser que je suis un utilisateur novice de C++.

Implémentation des solutions suggérées :

Concurrency::combinable> ligne;

parallel_for(0, hauteur, [&] (int y)
{
    std::vector ligneL = ligne.local();
    if (ligneL.capacity() < largeur) ligneL.reserve(largeur);

    bmp->GetLinearPixels(0, y, largeur, &ligneL[0]);

    for (int x = 0; x < largeur; x++)
    {
         BMM_Color_fl* pixel = &ligneL[x];
         //Faire quelque chose avec un pixel.
    }       
});

Comme suggéré, j'ai abandonné le malloc et l'ai remplacé par un vector+reserve.

0voto

salsaman Points 26

Au lieu que chaque thread appelle parallel_for(), faites-les appeler une autre fonction qui alloue la mémoire, appelle parallel_for(), puis libère la mémoire.

0voto

Ajay Points 5320

Vous pouvez utiliser la classe Concurrency::combinable pour y arriver. Je suis trop paresseux pour poster le code, mais je suis sûr que c'est possible.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X