并行处理数组索引的最佳方法?

时间:2016-09-17 16:34:38

标签: c++ arrays multithreading parallel-processing

我有以下情况:我有一个大小为L的盒子中的粒子列表,其中L是其中一个边的长度。

接下来,我将盒子分成单元格,其中L / cell_dim = 7.因此有7 * 7 * 7个单元格。

最后,我读完所有粒子,记下它们的位置,并计算它们所在的细胞。

我在openMP parallel for循环中完成了上述操作。但是,我需要以线程安全的方式捕获信息,这样我就不必遍历每个单元格的所有粒子。因此,我需要一些方法将粒子的任意子集并行记录到每个单元格中。

我现在使用的方法是使用OpenMP关键代码块。我有一个数组大小[7] [7] [7] [max_particles],其中max_particles是每个单元格中最高的粒子数,但是远远小于粒子总数。我记录了计数器数组大小[7] [7] [7]中添加的最后一个粒子的索引,并根据我的并行循环中的最新计数更新了单元格数组:

int cube[7][7][7][10];
int cube_counts[7][7][7]={0};

#pragma omp parallel for num_threads(a lot)  
for (int i = 0; i < num_particles; i++){
    cell_x = //cell calculation;
    cell_y = //ditto;
    cell_z = //...;

#pragma omp critical
    {
        cube_counts[cell_x][cell_y][cell_z] += 1;

        // for readability 
        int index = cube_counts[cell_x][cell_y][cell_z];

        cube[cell_x][cell_y][cell_z][index] = i;
    }
}

// rest in pseudo code: 

foreach cell: 
    adjacent_cell = cell2

    particle_countA = cube_counts[cellx][celly][cellz]
    particle_countB = cube_counts[cell2x][cell2y][cell2z]

   // these two for loops will cover ~2-4 particles,
   // so super small...as a result of the cell analysis above. 
    for particle in cell:
        for particle in cell2: 
             ...do stuff

虽然这样可行,但当我能够消除关键块时,它的速度提高了2倍以上(我在具有60个物理,240逻辑的英特尔协处理器上)。

如何在不需要关键块的情况下完成此操作?我想做了一个大阵列......但是当我迭代7 * 7 * 7 * 257(其中257是粒子计数)数组时,我失去了所有的东西。链接列表仍然具有竞争条件。

也许是某种无序的线程安全列表......?

1 个答案:

答案 0 :(得分:0)

可以进一步推动使用锁而不是关键部分:

您可以使用原子增量和原子分配伪调用(“intrinsics”),编译器将转换为正确的x86特定汇编程序指令。然而,这是平台甚至依赖于编译器。

如果你使用现代的c ++编译器(C ++ 11),那么std :: atomic_ *可能是最好的方法。