Erreur de débogage lors de l’appel de task :: spawn_root_and_wait dans tbb

Lorsque j’exécute ce code pour n> 11, une erreur de débogage s’est produite indiquant que abort () a été appelé. En utilisant le débogueur de Visual Studio, j’ai découvert qu’il se trouvait dans la tâche :: spawn_root_and_wait (test); ligne du code. Je ne sais pas pourquoi il fait ça. Lorsque j’ai exécuté le code en utilisant un tableau au lieu d’un vecteur, tout s’est bien passé, mais des erreurs d’access simultané se sont produites. Aucun conseil?

vector p; class PartTask: public task { public: const int n; int* sum; PartTask(int n_, int* sum_) : n(n_), sum(sum_) {} task* execute() { int a, b; int alpha = 0, beta = 0; for (int k = 1; k < n; k++) { a = n - (k*(3 * k - 1) / 2); b = n - (k*(3 * k + 1) / 2); //cout << n << "\t" << k << endl; //cout << a << "\t" << b << endl; if (a < 0 && b < 0) break; if (a < 0) alpha = 0; else if (p[a] != -1) alpha = p[a]; if (b < 0) beta = 0; else if (p[b] != -1) beta = p[b]; if (p[a] == -1 && p[b] == -1) { int x = 0, y = 0; PartTask& taskA = *new(allocate_child()) PartTask(a, &x); PartTask& taskB = *new(allocate_child()) PartTask(b, &y); set_ref_count(3); spawn(taskA); spawn_and_wait_for_all(taskB); p[a] = x%5; p[b] = y%5; alpha = p[a]; beta = p[b]; } else if (p[a] == -1) { int x = 0; PartTask& taskA = *new(allocate_child()) PartTask(a, &x); set_ref_count(2); spawn_and_wait_for_all(taskA); p[a] = x%5; alpha = p[a]; } else if (p[b] == -1) { int y = 0; PartTask& taskB = *new(allocate_child()) PartTask(b, &y); set_ref_count(2); spawn_and_wait_for_all(taskB); p[b] = y%5; beta = p[b]; } //cout << "\t" << alpha << "\t" << beta << "\t" << endl; if (k % 2 == 0) *sum += -1 * (alpha + beta); else *sum += alpha + beta; //cout << *sum < 0) *sum = *sum%5; else *sum = 5 + (*sum % 5); return NULL; } }; int main() { int n; cin >> n; vector temp(n,-1); p = temp; p.at(0) = 1 % 5; p.at(1) = 1 % 5; p.at(2) = 2 % 5; p.at(3) = 3 % 5; p.at(4) = 5 % 5; p.at(5) = 7 % 5; p.at(6) = 11 % 5; tick_count parallel_start = tick_count::now(); task_scheduler_init init; int summ = 0; PartTask& test = *new(task::allocate_root()) PartTask(n, &summ); task::spawn_root_and_wait(test); tick_count parallel_end = tick_count::now(); 

Le programme est mal formé pour les raisons suivantes qui ne sont pas liées au TBB lui-même.

Tout d’abord, il génère des access au vecteur par index négatif. Il a

  if (a < 0 && b < 0) break; 

mais dans le cas où seul 'a' ou seulement 'b' est négatif, il passe aux access p [a] et p [b]. C'est la raison principale pour laquelle cela échoue.

Deuxièmement, il atsortingbue simultanément des valeurs à l'élément vectoriel, ce qui entraînera au moins un résultat incohérent. STL réclame thread-safety pour std :: vector pour les access en lecture seule uniquement. tbb :: concurrent_vector ne protège pas non plus les access aux éléments. Veuillez utiliser des opérations mutex ou atomiques (par exemple, compare_and_swap() ) pour protéger l'access à un élément.

Et le conseil général, ce style de programmation TBB avec blocage de bas niveau n’est ni efficace (car la stack s’agrandit) ni lisible. Je recommanderais d'utiliser des interfaces de haut niveau comme tbb::parallel_invoke() ou tbb::task_group