我是一个多线程编程新手。最近,我有一个项目,我申请了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,等等,…)。这些省略的部分在每次运行中都是随机的,所以我认为这里的问题是关于缓存丢失。我对吗?请告诉我,任何帮助都是感激的。:)
问题是数组指针在生成的线程之间不同步,并且数组变量在每次循环迭代中递增。这只适用于线性执行。在您的代码片段中,多个线程正在访问数组中的相同元素,而数组的其他部分根本不处理。
为了解决这个问题,我建议在外部循环中计算索引,以便使用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;
}
}
}
顺便说一句:为什么你需要在这里进行手动循环展开?编译器应该自动完成。