我猜测即使从openmp中的共享数据读取也会导致一些并行开销,因为取决于处理器架构(如果不同的内核有自己的缓存...),可能需要刷新缓存以确保没有其他cpu在阅读之前修改了数据。
我是否正确地想到了这一点?
如果是这样,有没有办法告诉openmp(在intel编译器fwiw上)某些共享数据是不变的,所以不需要这样的缓存刷新?
如果答案是c ++ const
,那么一旦程序在运行时通过某个点,有一种简单的方法可以将非常量数据转换为常量数据,而无需实际重新分配内存吗?
更新
啊,好的。我现在记得在哪里我得到的印象const
在这种情况下是一件好事:http://www.akkadia.org/drepper/cpumemory.pdf,第6.4.1节。它与错误共享有关,其中与读写变量共享高速缓存行的只读变量会导致被读写变量标记为高速缓存行的代价。链接文档建议(例如使用gcc)将这些变量标记为__attribute__((section(something.else)))
,以确保它们存储在其他位置。
实际上这与我自己的情况无关 - 大型数组和stl数据容器,其中读/写粒度将跨越许多高速缓存行,并且在任何情况下都从不同的内存池分配。所以这些将自然地位于不同的缓存行上。没问题!
答案 0 :(得分:8)
我也在查看这个主题,并找到了Oracle的一般性能建议:
如果线程读取并行区域中的SHARED变量 然后,执行该区域,但不被任何线程写入 将该变量指定为FIRSTPRIVATE而不是SHARED。这个 避免通过解除引用指针来访问变量,并避免使用 缓存冲突。
Oracle OpenMP API User's Guide - Chapter 7 - Performance Considerations
答案 1 :(得分:5)
在多个内核之间共享只读数据没有开销。对于使用它的所有核心,相同的数据副本将位于缓存中。
只有当其中一个核心写入共享数据时,才会产生开销。在这种情况下,您将产生(可能很大的)开销,因为写入将使该缓存行的所有其他副本无效并强制它们从内存或从不同的缓存中获取它。
换句话说,当有人更改数据时,缓存只会“刷新”。没有定期的“刷新”。
所以你的问题的答案是:你不必做任何事情。没有办法告诉OpenMP或硬件数据是否恒定,const
除语法外没有任何影响。
答案 2 :(得分:0)
const
并不意味着内存是不变的。它意味着你对该内存的句柄不能写入它(这是微妙的不同):
int i = 3;
int const& j = i;
i = 4;
std::cout << j << "\n";
将打印4
,即使j
被限制为i
时值为3
。
因此,const
只能告诉你你不应该修改基础数据(并且编译器会强制执行它,到某一点)。除非直接应用于数据,否则它不会告诉任何有关数据本身的信息:
char const array[] = "Some value";
这里的存储是const
,值是不可变的,编译器可以自由地将它放在ROM中。