1

我是线程构建块的新手,并试图在 TBB 中编码 FFT 算法以获得一些实践经验。在这种算法的情况下,我只能并行化最里面的循环。但是通过这样做,性能已经下降到无法接受的程度(超过一千次)。我尝试过最大为 2^20 的数组大小,但结果相同。我的代码如下

for(stage1=0;stage1 < lim;stage1 ++)
{
    butterfly_index1 = butterfly_index2;
    butterfly_index2 = butterfly_index2 + butterfly_index2; 
    k = -1*2*PI/butterfly_index2;
    k_next = 0.0;
    for(stage2 = 0 ; stage2 < butterfly_index1;stage2++)
    {
        sine=sin(k_next);
        cosine = cos(k_next);
        k_next = k_next + k;
        FFT. sine = &sine;
        FFT.cosine = &cosine;
        FFT.n2 = &butterfly_index2;
        FFT.loop_init = &stage2;
        FFT.n1 = &butterfly_index1;
        parallel_for(blocked_range<int>(
                        stage2,SIZE,SIZE/4),FFT,simple_partitioner()); 
    }
}   

parallel_loop 的主体是

void operator()(const blocked_range<int> &r)const
{
    for(int k = r.begin(); k != r.end(); k++)
    {   
        if(k != *loop_init)
        {
            if((k - (*loop_init))% (* n2)!= 0)
                continue;
        }           
        temp_real = (*cosine) * X[k + *n1].real - (*sine) * X[k + *n1].img;
        temp_img = (*sine)* X[k + *n1].real + (*cosine) * X[k + *n1].img;
        X[k + *n1].real = X[k].real - temp_real;
        X[k + *n1].img = X[k].img - temp_img;
        X[k].real = X[k].real + temp_real;
        X[k].img = X[k].img + temp_img; 
    }
}

如果我用正常循环替换它,那么事情是正确的。

4

2 回答 2

1

对于非常短的工作负载,由于线程创建的开销,可能会发生巨大的减速。对于数组中的 2^20 个元素,我不相信会发生如此巨大的性能下降。

另一个导致性能下降的重要原因是编译器在 TBBfied 之后无法优化(特别是矢量化)代码。查明您的编译器是否可以生成矢量化报告,并查找串行版本和 TBB 版本之间的差异。

减速的一个可能来源可能是parallel_for 的主体类的复制构造函数,因为主体被复制了很多。但是给定的代码在这方面看起来并不可疑:似乎主体包含一些指针。无论如何,看看它是否可能是一个问题。


另一个常见的显着开销来源是太细粒度的并行性,即很多任务,每个任务都只包含很少的工作。但是这里也不是这种情况,因为blocked_range的第三个参数中的grainsize SIZE/4指定了body的operator()()每个算法最多会被调用4次。

我建议不要为初始实验指定 simple_partitioner 和 grainsize,而是让 TBB 动态分配工作。如有必要,您可以稍后对其进行调整。

于 2011-04-03T09:36:34.403 回答
0

我的代码的问题是随着 n2 变量的增加工作量减少。因此,随着 out 循环的进行,parallel_for 的工作量变为一半,并且经过几次迭代后,它变得太小而无法通过使用 TBB 来提高性能。因此,解决方案是仅在内部循环的工作负载足够时才对迭代进行并行化,并为其余的迭代序列化内部循环。其次,包含条件检查 (k != r.end()) 的“for”循环头也会降低性能。解决方案是将 r.end() 替换为初始化为 r.end() 的本地定义变量

感谢英特尔软件论坛帮助解决此问题

于 2011-04-03T21:23:58.970 回答