2017-08-24 5 views
0

Conceptuellement, comment bloquer une section critique à l'intérieur d'un appel tbb::parallel_for en utilisant tbb:spin_mutex? La section critique est inférieure à 20 instructions donc spin_mutex est idéal. Par exemple, le code fictif suivant explique la situation:TBB spin_mutex en parallèle_pour bloquer une section critique

function() { 
    // I'm using lambda functions in parallel_for call here. The parallel_for 
    // is multithreading across the size of the vector customVec 
    tbb::parallel_for(
     tbb::blocked_range<vector<CustomeType>::iterator>(customVec.begin(), customVec.end(), 1), 
     [&](tbb::blocked_range<vector<CustomType>::iterator> customVec) { 
      for (vector<CustomType>::iterator it = customVec.begin(); it != customVec.end(); it++) { 
       CustomType item = *it; 
       ... 
       ... 

       // This is the cross-functional call that each thread will call 
       // critical section is in-side the functionA 
       item->functionA(param1, param2); 
      } 

      ... 
      ... 
     } 
    ); 

    ... 
    ... 
} 

Et fonctionn:

functionA (Type1 param1, Type2 param2) { 
    if (conditionX) { 
     /* This file read is the critical section. So basically, need to 
     block multiple threads reading the same file to reduce I/O cost 
     and redundancy. Since file read can be stored in a global variable 
     that can be accessed in memory by other threads */ 

     fileRead(filename); // Critical line that need to be protected 
    } 
    ... 
    ... 
} 

Ce que je me bats avec le mutex est comment je peux configurer spin_mutex en sorte que functionA() partagé à travers le fil et les threads ne vont pas se dépasser l'un l'autre et essayer d'exécuter la section critique en même temps.

Note: supposons que function() et functionA() appartient à deux classes distinctes C++ et il n'y a pas d'héritage de classes entre les deux classes qui ont function() et functionA() comme fonctions membres

Répondre

0

Je viens de trouver une solution. Peut-être pas l'optimal mais résolu le problème que j'avais. Donc, le poster comme une réponse pour quelqu'un qui pourrait rencontrer le même problème.

Fondamentalement, la solution consiste à définir spin_mutex objet en dehors du parallel_for et le passer à l'appel de la fonction comme une référence. Je l'ai posté ci-dessous le même exemple de code de la question avec la solution:

tbb::spin_mutex mtx; // Declare spin_mutex object 
function() { 
    // I'm using lambda functions in parallel_for call here. The parallel_for 
    // is multithreading across the size of the vector customVec 
    tbb::parallel_for(
     tbb::blocked_range<vector<CustomeType>::iterator>(customVec.begin(), customVec.end(), 1), 
     [&](tbb::blocked_range<vector<CustomType>::iterator> customVec) { 
      for (vector<CustomType>::iterator it = customVec.begin(); it != customVec.end(); it++) { 
       CustomType item = *it; 
       ... 
       ... 

       // This is the cross-functional call that each thread will call 
       // critical section is in-side the functionA 
       item->functionA(param1, param2, mtx); // pass object as a reference 
      } 

      ... 
      ... 
     } 
    ); 

    ... 
    ... 
} 

et fonctionn:

// Pass the spin_mutex object by reference 
functionA (Type1 param1, Type2 param2, tbb::spin_mutex& mtx) { 
    if (conditionX) { 
     /* This file read is the critical section. So basically, need to 
     block multiple threads reading the same file to reduce I/O cost 
     and redundancy. Since file read can be stored in a global variable 
     that can be accessed in memory by other threads */ 

     // Acquire a scope lock 
     { 
      tbb::spin_mutex::scoped_lock lock(mtx); 
      fileRead(filename); // Critical line that need to be protected 
     } 
    } 
    ... 
    ... 
} 
1

Vous voudrez peut-être envisager d'utiliser un spin_mutex statique dans la fonction:

functionA (Type1 param1, Type2 param2) { 
    if (conditionX) { 
     /* This file read is the critical section. So basically, need to 
     block multiple threads reading the same file to reduce I/O cost 
     and redundancy. Since file read can be stored in a global variable 
     that can be accessed in memory by other threads */ 

     // A static mutex that is shared across all invocations of the function. 
     static tbb::spin_mutex mtx; 
     // Acquire a lock 
     tbb::spin_mutex::scoped_lock lock(mtx); 
     fileRead(filename); // Critical line that need to be protected 
    } 
    ... 
    ... 
} 

Faites attention à ce que cela fonctionne uniquement avec C++ 11 et versions ultérieures (car vous avez besoin de la "magie statique", c'est-à-dire de la sécurité des threads de l'initialisation des variables statiques).