1

我是多线程编程的新手。最近,我有一个项目,我将 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-ed)。但也有可能会省略数组的某些部分(第一个元素到第 300 个元素是 AND-ed,第 301 个元素到第 505 个元素不是 AND-ed,第 506 个元素到第 707 个元素是 AND-ed,等等, ...)。这些省略的部分在每次运行中都是随机的,所以我认为这里的问题是关于缓存未命中。我对吗?请告诉我,任何帮助表示赞赏。:)

4

1 回答 1

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;
            }
        }
    }

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

于 2014-05-30T14:36:56.877 回答