Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 多核上的错误共享_C++_Parallel Processing_Openmp_Cpu Cache_False Sharing - Fatal编程技术网

C++ 多核上的错误共享

C++ 多核上的错误共享,c++,parallel-processing,openmp,cpu-cache,false-sharing,C++,Parallel Processing,Openmp,Cpu Cache,False Sharing,以下程序中是否会发生错误共享 内存 1个数组分为4个相等的区域:[A1、A2、B1、B2] 整个阵列可以放入实际程序中的一级缓存中 每个区域填充为64字节的倍数 步骤 1. thread 1 write to region A1 and A2 while thread 2 write to region B1 and B2. 2. barrier 3. thread 1 read B1 and write to A1 while thread 2 read B2 and write to A

以下程序中是否会发生错误共享

内存

  • 1个数组分为4个相等的区域:
    [A1、A2、B1、B2]
  • 整个阵列可以放入实际程序中的一级缓存中
  • 每个区域填充为64字节的倍数
步骤

1. thread 1 write to region A1 and A2 while thread 2 write to region B1 and B2.
2. barrier
3. thread 1 read B1 and write to A1 while thread 2 read B2 and write to A2.
4. barrier
5. Go to step 1.
测试

#include <vector>
#include <iostream>
#include <stdint.h>
int main() {
    int N = 64;
    std::vector<std::int32_t> x(N, 0);
    #pragma omp parallel
    {
        for (int i = 0; i < 1000; ++i) {
            #pragma omp for
            for (int j = 0; j < 2; ++j) {
                for (int k = 0; k < (N / 2); ++k) {
                    x[j*N/2 + k] += 1;
                }
            }
            #pragma omp for
            for (int j = 0; j < 2; ++j) {
                for (int k = 0; k < (N/4); ++k) {
                    x[j*N/4 + k] += x[N/2 + j*N/4 + k] - 1;
                }
            }
        }
    }
    for (auto i : x ) std::cout << i << " ";
    std::cout << "\n";
}
32 elements of 500500 (1000 * 1001 / 2)
32 elements of 1000

您的代码中存在一些错误共享,因为
x
不能保证与缓存线对齐。填充不一定足够。在您的示例中,
N
非常小,这可能是一个问题。注意,在您的示例中,最大的开销可能是工作共享和线程管理。如果
N
足够大,即
数组大小/线程数>>缓存线大小
,则错误共享不是相关问题

在缓存使用方面,从代码中的不同线程交替写入
A2
也不是最优的,但这不是错误的共享问题

注意,不需要拆分循环。若您在一个循环中连续地访问内存中的索引,那个么一个循环就可以了

#pragma omp for
for (int j = 0; j < N; ++j)
    x[j] += 1;
#pragma omp for
对于(int j=0;j
如果您真的很小心,您可以添加
计划(静态)
,那么您可以保证均匀连续的单词分布


请记住,错误共享是一个性能问题,而不是正确性问题,并且只有在频繁发生时才相关。典型的错误模式是写入
vector[my\u thread\u index]

如何阻止线程在不同的内核上被重新调度?@RichardCritten我不知道。我希望:1。
#pragma omp parallel
行创建两个线程,每个线程都有一个内核。2.其余的行只使用两个现有的omp线程。我能做到吗?我现在正在考虑算法。更新:如果我设置了环境变量,可能会打开mp can:如果不能,那么我将尝试学习pthreads。如果整个数组可以加载到单个缓存线中,那么您将遇到问题。为了避免错误共享,您必须将正在处理的每个段放在不同的缓存线中。@NathanOliver:如果整个阵列勉强适合
n_cores x一级缓存大小
,那就可以了?如果cpu内核从不在同一时间写入同一缓存线,这会好吗?你必须担心的是缓存线。这通常是64字节。您可以让不同的内核同时在不同的缓存线上工作。非常感谢您的回答。我正在使用特征库(simd线性代数库)。因此,内存对齐应该很好。在这种情况下,线程管理意味着障碍?线程管理将是障碍,以及在参与线程之间分割工作(即循环迭代)所必需的任何东西。由于积极的硬件预取,您还可能存在性能问题。我认为这是错误的共享(或一些相同概念的扩展),尽管它不是教科书的定义。