本文介绍了在tbb中调用task :: spawn_root_and_wait时出现调试错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我运行这个代码为n> 11我得到一个调试错误,说abort()已被调用。使用visual studio调试器,我发现它在任务:: spawn_root_and_wait(test);行的代码。我不知道为什么这样做。当我运行代码使用数组而不是一个向量它运行正常,但我得到并发错误。任何建议?

When I run this code for n > 11 I get a debug error saying that abort() has been called. Using the visual studio debugger I found that it was on the task::spawn_root_and_wait(test); line of the code. I have no idea why it is doing this. When I ran the code using an array instead of a vector it ran fine but I was getting concurrency errors. Any advice?

   vector<int> 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 << endl;
        }

        if (*sum > 0)
             *sum = *sum%5;
        else
            *sum = 5 + (*sum % 5);

        return NULL;
    }

};




   int main()
   {    
    int n;
    cin >> n;
    vector<int> 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();


推荐答案

没有连接到TBB本身。

The program is ill-formed for the following reasons which are not connected to TBB itself.

首先,它通过负索引生成对向量的访问。它具有

First, it generates accesses to the vector by negative index. It has

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

但是在只有a或只有b a]和p [b]访问。这是它失败的主要原因。

but in case when only 'a' or only 'b' is negative, it proceeds to p[a] and p[b] accesses. It is the main reason why it fails.

其次,它同时向vector元素赋值,至少会导致不一致的结果。 STL声明std :: vector的线程安全性仅用于只读访问。 tbb :: concurrent_vector也不保护元素访问。请使用互斥或​​原子操作(例如 compare_and_swap())来保护对元素的访问。

Second, it assigns values to vector element concurrently, it will lead to inconsistent result at least. STL claims thread-safety for std::vector for read-only accesses only. tbb::concurrent_vector does not protects element accesses either. Please use mutex or atomic operations (e.g. compare_and_swap()) to protect access to an element.

建议,这种低级阻塞式的TBB编程既不高效(因为堆栈增长)也不可读。我建议使用高级接口,例如 tbb :: parallel_invoke() tbb :: task_group

And the general advice, this low-level blocking-style of TBB programming is neither efficient (because the stack grows) nor readable. I'd recommend using high-level interfaces like tbb::parallel_invoke() or tbb::task_group

这篇关于在tbb中调用task :: spawn_root_and_wait时出现调试错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 22:05