我正在尝试使用英特尔线程构建模块调试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);
}
答案 0 :(得分:0)
我终于解决了它。它来自我的代码。调用spawn_and_wait_for_all()
时,它会调用先前生成的任务的execute()
方法,但gdb似乎无法在回溯中显示该方法。对我有用的是将线程数设置为1并执行良好的旧cout << endl << "Checkpoint" << endl
调试。
在本案中,我忘了在execute()
的第一个if中返回。任何代码的弱点似乎都会对TBB造成严重后果。