线程构建块分段错误

时间:2018-05-02 18:20:54

标签: c++ tbb

我正在尝试使用英特尔线程构建模块调试C ++代码,遵循此处的过程 - dbfiddle

我尝试使用一个线程运行代码,并将TBB_USE_DEBUG设置为1(我在此处询问了之前的问题 - Debugging in threading building Blocks)。但是,我得到一个奇怪的分段错误。这是gdb的回溯。

#0  0x00007ffff793fbc1 in ?? () from /usr/lib/x86_64-linux-gnu/libtbb.so.2
#1  0x000000000040d2cb in tbb::task::spawn_and_wait_for_all (child=..., this=0x7ffff63b7a40)
    at /usr/include/tbb/task.h:728
#2  MpsTask1::execute (this=0x7ffff63b7a40)
    at /capps/mps_implementations.hpp:102
#3  0x00007ffff793ffdd in ?? () from /usr/lib/x86_64-linux-gnu/libtbb.so.2
#4  0x000000000040d2cb in tbb::task::spawn_and_wait_for_all (child=..., this=0x7ffff63b7d40)
    at /usr/include/tbb/task.h:728
#5  MpsTask1::execute (this=0x7ffff63b7d40)
    at /capps/mps_implementations.hpp:102

我对此回溯感到非常困惑,因为我无法控制库内发生的事情。我犯的错误是否可能导致spawn_root_and_wait失败?

这是我的代码(没有构造函数和析构函数来保持简短)。其目的是通过缩减操作计算数组的最大前缀和。它递归地划分数组,直到块足够小,然后加入结果。我知道我可以使用TBB parallel_reduce模板解决这个问题,但我的目标是了解TBB基于任务的编程是如何工作的。

class MpsTask1: public task {
public:

    task* execute(){
        if(size <= Cutoff){

            for(int i = left; i != right; i++){
                *sum = *sum + array[i]);

                if (*sum <= *mps){
                    *mps = *sum;
                    *position = i+1; 
                }
            }

            memo[depth][index] = cutoff;

        }else{
            // Parameters for subtasks
            int middle = (right+left)/2;
            int sizel = middle - left;
            int sizer = right - middle;
            int newDepth = depth + 1;
            int lIndex = 2*index;
            int rIndex = lIndex + 1;

            // Variables for results
            int lPos = left;
            int rPos = middle;
            double lsum, rsum, lmps, rmps;

            // Create subtasks
            set_ref_count(3);

            MpsTask1& lTask = *new(allocate_child()) MpsTask1(Cutoff,array,sizel,&lsum,&lmps,&lPos,memo,newDepth,lIndex,left,middle);
            spawn(lTask);

            MpsTask1 &rTask = *new(allocate_child()) MpsTask1(Cutoff,array,sizer,&rsum, &rmps,&rPos,memo,newDepth,rIndex,middle,right);

            spawn_and_wait_for_all(rTask);

            // Join results
            rmps = lsum+rmps;
            *sum = lsum+rsum;
            if(*mps <= rmps){
                *mps = rmps;
                *position = rPos;
                memo[depth][index] = rightChild;
            }
            else{
                *mps_interval = lmps;
                *position = lPos;
                memo[depth][index] = leftChild;
            }
            return NULL;
        }
    }

private:
    /* Below this size, the mps and sum are computed sequentially */
    int Cutoff;
    /* Input array and its size */
    double* array;
    int size;    
    /* Identification of the task */
    int depth;
    int index;
    int left;
    int right;
    /* Intervals for sum and mps */
    double* sum;
    double* mps;
    /* Position of the mps */
    int* position;
    // Status : left child, right child, or cutoff
    Status** memo;
};

void parallel_mps(double* array, int size, int Cutoff){
    // Create variables for result
    double sum = 0., mps = 0.;
    int position = 0;

    // Initialization of memo
    ....
    // Finished initialization of memo


    MpsTask1& root = *new(task::allocate_root()) MpsTask1(Cutoff,array,size,&sum,&mps,&position,memo);

    task::spawn_root_and_wait(root);
}

1 个答案:

答案 0 :(得分:0)

我终于解决了它。它来自我的代码。调用spawn_and_wait_for_all()时,它会调用先前生成的任务的execute()方法,但gdb似乎无法在回溯中显示该方法。对我有用的是将线程数设置为1并执行良好的旧cout << endl << "Checkpoint" << endl调试。 在本案中,我忘了在execute()的第一个if中返回。任何代码的弱点似乎都会对TBB造成严重后果。