Cilk_for在数组中返回错误的数据

时间:2014-05-29 04:17:42

标签: parallel-processing intel cilk-plus

我是多线程编程的新手。最近,我有一个项目,我将cilk_for应用到其中。这是代码:。

void myfunction(short *myarray)
{
m128i *array = (m128i*) myarray
cilk_for(int i=0; i<N_LOOP1; i++)
    {
        for(int z = 0; z<N_LOOP2; z+=8)
        {
            array[z]        =  _mm_and_si128(array[z],mym128i);
            array[z+1]        =  _mm_and_si128(array[z+1],mym128i);
            array[z+2]        =  _mm_and_si128(array[z+2],mym128i);
            array[z+3]        =  _mm_and_si128(array[z+3],mym128i);
            array[z+4]        =  _mm_and_si128(array[z+4],mym128i);
            array[z+5]        =  _mm_and_si128(array[z+5],mym128i);
            array[z+6]        =  _mm_and_si128(array[z+6],mym128i);
            array[z+7]        =  _mm_and_si128(array[z+7],mym128i);
            array+=8;
        }
    }
}

上面的代码运行后,发生了荒谬的事情。数组中的数据未正确更新。例如,如果我有一个包含1000个元素的数组,则阵列有可能正确更新(1000个元素是AND编辑的)。但是也有可能省略数组的某些部分(第一个元素到第300个元素是AND-ed,第301个元素到第505个元素没有AND,第506个元素到第707个元素是AND-ed等等, ...)。这些省略的部分在每次运行中都是随机的,所以我认为这里的问题是关于缓存未命中。我对吗?请告诉我,任何帮助表示赞赏。 :)

1 个答案:

答案 0 :(得分:0)

问题是数组指针在cilk产生的线程之间没有同步,并且你的数组变量在每次循环迭代中都会递增。这仅适用于线性执行。在您的代码片段中,多个线程正在访问阵列中的相同元素,而阵列的其他部分根本不会被处理。

为了解决这个问题,我建议计算外部循环中的索引,以便使用Cilk生成的每个线程都能够独立地计算地址。也许你可以这样做:

void myfunction(short *myarray)
    {
    cilk_for (int i=0; i<N_LOOP1; i++)
        {
            m128i *array = (m128i*) myarray + i * N_LOOP2 * 8;
            for(int z = 0; z<N_LOOP2; z+=8)
            {
                array[z]        =  _mm_and_si128(array[z],mym128i);
                array[z+1]        =  _mm_and_si128(array[z+1],mym128i);
                array[z+2]        =  _mm_and_si128(array[z+2],mym128i);
                array[z+3]        =  _mm_and_si128(array[z+3],mym128i);
                array[z+4]        =  _mm_and_si128(array[z+4],mym128i);
                array[z+5]        =  _mm_and_si128(array[z+5],mym128i);
                array[z+6]        =  _mm_and_si128(array[z+6],mym128i);
                array[z+7]        =  _mm_and_si128(array[z+7],mym128i);
                array+=8;
            }
        }
    }

顺便说一句:为什么你需要在这里展开手动循环?编译器应该自动执行此操作。