C++ 17添加std::hardware_destructive_interference_size和std::hardware_constructive_interference_size.首先,我认为这只是获取L1缓存行大小的可移植方式,但这是过于简单化.
问题:
static constexpr.如果您构建二进制文件并在具有不同缓存行大小的其他计算机上执行它,这不是问题吗?当您不确定您的代码将运行在哪台机器上时,如何防止错误共享?为了防止错误共享,我想将数组的每个元素对齐到缓存行.所以首先我需要知道缓存行的大小,因此我为每个元素分配了大量的字节.其次,我希望数组的开始与高速缓存行对齐.
我使用的是Linux和8核x86平台.首先,我如何找到缓存行大小.其次,如何与C中的缓存行对齐.我正在使用gcc编译器.
因此,假设高速缓存行大小为64,结构将遵循.
element[0] occupies bytes 0-63
element[1] occupies bytes 64-127
element[2] occupies bytes 128-191
Run Code Online (Sandbox Code Playgroud)
等等,当然假设0-63与高速缓存行对齐.
有没有办法在C++中确定CPU的缓存大小?我有一个处理大量数据的算法,我想将这些数据分解成块,以便它们适合缓存.这可能吗?你能否给我一些有关缓存大小的编程的其他提示(特别是在多线程/多核数据处理方面)?
谢谢!
作为一项学校作业,我需要找到一种方法来获取L1数据缓存行大小,而无需读取配置文件或使用api调用.假设使用内存访问读/写时序来分析和获取此信息.那我该怎么做呢?
在完成另一部分任务的不完整尝试中,为了找到缓存的级别和大小,我有:
for (i = 0; i < steps; i++) {
arr[(i * 4) & lengthMod]++;
}
Run Code Online (Sandbox Code Playgroud)
我想也许我只需要改变第2行,(i * 4)部分?所以一旦我超过缓存行大小,我可能需要更换它,这需要一些时间?但它是如此直截了当?所需的块可能已经存在于内存中?或者perpahs我仍然可以依靠这样一个事实:如果我有足够大的steps,它仍然可以非常准确地运作?
UPDATE
下面是对GitHub的尝试 ...主要部分如下
// repeatedly access/modify data, varying the STRIDE
for (int s = 4; s <= MAX_STRIDE/sizeof(int); s*=2) {
start = wall_clock_time();
for (unsigned int k = 0; k < REPS; k++) {
data[(k * s) & lengthMod]++;
}
end = wall_clock_time();
timeTaken = ((float)(end - start))/1000000000;
printf("%d, %1.2f \n", s * sizeof(int), timeTaken); …Run Code Online (Sandbox Code Playgroud) 我希望我的程序读取它在C++中运行的CPU的缓存行大小.
我知道这不能轻松完成,所以我需要一个适用于Linux的解决方案和另一个适用于Windows的解决方案(其他系统的解决方案可能对其他人有用,所以如果你了解它们就发布它们).
对于Linux,我可以读取/ proc/cpuinfo的内容并解析以cache_alignment开头的行.也许有一种更好的方式来调用API.
对于Windows,我根本不知道.
我是一个相当有经验的OpenMP用户,但我遇到了一个令人费解的问题,我希望有人可以提供帮助.问题是,一个简单的哈希算法对堆栈分配的数组表现良好,但对堆上的数组表现不佳.
下面的示例使用i%M(i模数M)来计算相应阵列元素中的每个第M个整数.为简单起见,假设N = 1000000,M = 10.如果N%M == 0,那么结果应该是bins []的每个元素都等于N/M:
#pragma omp for
for (int i=0; i<N; i++)
bins[ i%M ]++;
Run Code Online (Sandbox Code Playgroud)
数组bins []对每个线程都是私有的(我在之后对关键部分中所有线程的结果进行求和).
当在堆栈上分配bins []时,程序运行良好,性能与内核数量成比例缩放.
但是,如果bin []在堆上(指向bin []的指针在堆栈上),性能会急剧下降.这是一个重大问题!
我希望使用OpenMP将某些数据的binning(散列)并行化为堆数组,这是一个重大的性能影响.
绝对不是像所有线程试图写入同一内存区域那样愚蠢的东西.这是因为每个线程都有自己的bins []数组,结果对于堆栈和堆栈分配的bin都是正确的,并且单线程运行的性能没有差别.我使用GCC和英特尔C++编译器在不同的硬件(Intel Xeon和AMD Opteron)上重现了这个问题.所有测试都在Linux(Ubuntu和RedHat)上进行.
似乎没有理由将OpenMP的良好性能限制在堆栈数组中.
任何猜测?也许对线程的访问是通过Linux上的某种共享网关进行的?我该如何解决这个问题?
完整的程序如下:
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
int main(const int argc, const char* argv[])
{
const int N=1024*1024*1024;
const int M=4;
double t1, t2;
int checksum=0;
printf("OpenMP threads: %d\n", omp_get_max_threads());
//////////////////////////////////////////////////////////////////
// Case 1: stack-allocated array
t1=omp_get_wtime();
checksum=0;
#pragma omp parallel
{ // Each openmp thread …Run Code Online (Sandbox Code Playgroud) 我感兴趣的是仅针对地址空间区域刷新缓存(L1,L2和L3),例如从地址A到地址B的所有缓存条目.在Linux中是否存在从用户或内核空间执行此操作的机制?
背景:我已经实现了一种随机算法,需要随机排序以获得最佳收敛.但是,这样做显然会破坏内存局部性.我发现通过预取下一个迭代的数据,性能下降最小化.
我可以使用简单的,主要是OS +编译器 - 便携式方式预取n个缓存行_mm_prefetch- 但是缓存行的长度是多少?现在,我正在使用64的硬编码值,这在x64处理器上似乎是现在的常态 - 但我不知道如何在运行时检测到这一点,并且去年的一个问题没有找到简单的解决方案.
我在Windows上看到了GetLogicalProcessorInformation,但我对使用如此简单的复杂API非常谨慎,而且无论如何都无法在mac或linux上运行.
也许有一些完全可以预取由字节(或单词等)标识的内存区域的其他API /内在函数,并允许我在不知道缓存行长度的情况下进行预取?
基本上,有没有一个合理的选择_mm_prefetch用#define CACHE_LINE_LEN 64?
我做了一些关于缓存未命中优化的阅读,并开始了解这个stdlib函数.它为优化做了某种内存对齐,但是可以帮助我解释一下这个函数到底做了什么吗?它需要3个参数:void**memptr,size_t alignment,size_t size
我没有得到的部分是文档的含义
"分配的大小由指定的边界字节对齐排列 ......"
我从阅读中理解的是功能类型分配一个大小大小的内存块,但在那之后,我没有得到它们的意思是"边界" ......是不是将内存块分解成更小的块对齐大小?
以下是文档:http://www.opengroup.org/onlinepubs/9699919799/functions/posix_memalign.html
高速缓存行通常为64 字节,也存在其他大小。
我非常简单的问题是:这个数字背后是否有任何理论,或者它只是背后的工程师无疑所做的大量测试和测量的结果?
不管怎样,我想知道这些是什么(理论,如果有的话,以及决定背后的各种测试)。
c++ ×6
caching ×4
c ×3
linux ×3
cpu ×2
cpu-cache ×2
performance ×2
64-bit ×1
alignment ×1
arm ×1
c++17 ×1
concurrency ×1
heap ×1
linux-kernel ×1
memory ×1
openmp ×1
optimization ×1
stack ×1
windows ×1
x86 ×1