数据未写入共享内存

时间:2017-07-01 10:07:22

标签: c multithreading caching openmp cpu

我正在调试一个从多个线程写入数组的函数。作为MWE,它将每个元素设置为零并递增它,直到array[i]包含i >> 13。每个元素仅由单个线程修改。

但是当在写入期间另一个线程从数组中读取时,即使读取线程不使用该值,也不会更改数组的部分内容。

void test(int* array, int* backup, int length) 
{
#pragma omp parallel
{
    #pragma omp for schedule(static) 
    for(int i = 0; i<length; i++) {
        #pragma omp atomic write
        array[i] = 0;
        int target = i >> 13;
        int tmp = 0;
        int j = i + 5000000;
        while (array[i] < target) {
            j+=15; if (j >= length) j = 0;
            int r;
            #pragma omp atomic read
            r = array[j];
            tmp += r;
            #pragma omp atomic
            array[i]++;
        }
        backup[i]=array[i] * 10 + (tmp & 1);
    }          
}
}

当该函数在例如使用0xABCD1234(-1412623820)初始化的1000万个元素阵列上运行时,array[1974732]之后的20个元素变为11 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 -1412623820 241 241 241。 (从不相同的受影响元素)

但是,未读数组backup[i]/10始终包含正确的值,例如241所有上述元素。

似乎每个处理器在其缓存中写入正确的值,然后有时会忘记更新主内存。或者也许ram坏了而忽略了写作?它发生在64核AMD Opteron 6272上,问题不受gcc优化级别,更多刷新/围栏指令或原子编译指示的影响。

剩余测试代码:

int gbackup[10000000];
int main(int argc, char *argv[]) 
{

    int length = 10000000;
    int* seq = malloc(length * sizeof(length));
    for (int i=0;i<length;i++) 
        seq[i] = i >> 13;

    for (int a=1;a<500;a++)
    {
        int* par = malloc(length * sizeof(length));
        for (int i=0;i<length;i++)
            par[i] = gbackup[i] =  0xABCD1234; 
        parallel_implementation(par, gbackup, length);
        if (memcmp(seq, par, length*sizeof(int)) != 0)  {     
            printf("\nAborting.\n");
            return -1;
        }
    }

    return 0;
}

更新

实际上它似乎与读取无关。或许它变得更糟。即便这样现在也失败了,并且保留了不变或低于i>>13的数组元素:

void test(int* array, int*, int length) 
{
#pragma omp parallel
{
    #pragma omp for schedule(static) 
    for(int i = 0; i<length; i++) {
        #pragma omp atomic write
        array[i] = 0;
        int target = i >> 13;
        while (array[i] < target) {
            #pragma omp atomic
            array[i]++;
        }   
    }          
}
}

0 个答案:

没有答案