Tag: 缓存

通过恒定长度遍历数组的访问时间

我想测量缓存的速度(我问了一个问题 ),所以我写了这段代码: #include #include #include const int mod = 100000007; volatile int f[100000007]; volatile int *p; int main() { FILE *f1; f1=fopen(“CacheTest.txt”,”w”); for(int l=1;l<=100000;) { clock_t st,ed; st=clock(); int now=0; for(int i=0;i=mod) now-=mod; } ed=clock(); double extime=(double)(ed-st)/CLOCKS_PER_SEC; st=clock(); now=0; for(int i=0;i=mod) now-=mod; } ed=clock(); double cost=(double)(ed-st)/CLOCKS_PER_SEC; fprintf(f1,”length %d costs %f seconds access time:%f\n”,l,cost,cost-extime); printf(“length %d […]

使用英特尔的PIN工具计算程序中缓存命中/未命中的数量

我一直在尝试编写一个pintool来检测给定程序中的缓存命中和未命中。 我发现有一些调用,如INS_IsMemoryRead / Write,以确定指令是否为LD / ST。 有没有办法确定指令是否有缓存命中或未命中? 如果是这样,是否也可以获得从缓存/内存中获取数据所花费的周期数?

缓存友好的矩阵移位function

我想将2D方阵的第一行移到最后一行。 所以如果我有像A这样的矩阵,我想得到B. 我可以使用两个简单的for循环来做到这一点。 例如 void shift(int M, int N, int A[M][N]){ int i, j,temp; for (i = 1; i < M; i++){ for (j = 0; j < N; j++){ temp=A[i][j]; A[i][j]=A[i-1][j]; A[i-1][j]=temp; } } } 但我希望尽可能少地缓存未命中数。 有关如何做到这一点的任何提示?

通过延迟/性能测量确定NUMA布局

最近我一直在观察内存密集型工作负载中的性能影响,我无法解释。 试图找到底部我开始运行几个微基准测试,以确定常见的性能参数,如缓存行大小和L1 / L2 / L3缓存大小(我已经知道了,我只是想看看我的测量是否反映了实际值)。 对于缓存行测试,我的代码大致如下(Linux C,但这个概念当然与Windows等相似): char *array = malloc (ARRAY_SIZE); int count = ARRAY_SIZE / STEP; clock_gettime(CLOCK_REALTIME, &start_time); for (int i = 0; i < ARRAY_SIZE; i += STEP) { array[i]++; } clock_gettime(CLOCK_REALTIME, &end_time); // calculate time per element here: [..] 从1到128改变STEP表明从STEP=64开始,我看到每个元素的时间没有进一步增加,即每次迭代都需要获取一个主导运行时的新缓存行。 改变ARRAY_SIZE从1K到16384K保持STEP=64我能够创建一个很好的绘图,展示一个大致对应于L1,L2和L3延迟的步骤模式。 为了获得可靠的数字,有必要多次重复for循环,对于非常小的arrays大小甚至100,000次。 然后,在我的IvyBridge笔记本上,我可以清楚地看到L1结束于64K,L2处于256K,甚至L3处于6M。 现在谈谈我的真正问题:在NUMA系统中,任何一个核心都将获得远程主内存甚至共享缓存,这些缓存不一定与其本地缓存和内存一样接近。 我希望看到延迟/性能的差异,从而确定在保持快速缓存/部分内存时我可以分配多少内存。 为此,我改进了我的测试,以1/10 MB块的forms遍历内存,分别测量延迟,然后收集最快的块,大致如下: for (int chunk_start […]

需要随机访问时改善随机存储器访问

我正在做的基本概念 完成联盟结构形成问题/组合拍卖。 给定一组N个代理,其中该代理集的不相交子集产生最佳结果。 例如, Agents = {a,b}及其值 {a} = 2 {b} = 3 {a,b} = 4 在这种情况下, {{a},{b}} = 5的联盟将给出最佳结果,其中它是{a,b}的成对不相交子集。 因此,简而言之,问题在于拆分集合并检查任何拆分总和是否大于原始集合。 (这部分与生成分裂以及如何表示数据一样好。) 我如何表示数据基本上是一个值数组,其中索引是设置配置(一个集合表示为整数)。 对于上面的例子: int val[4] = {0,2,3,4}其中set {a} = 01 = index 1 {b} = 10 = index 2 {a,b} = 11 = index 3 因此该集合充当值数组中的索引。 问题在于,这给出了随机存储器访问,给定了大量需要考虑2^n值的代理。 跳过这里的记忆访问问题 例如,在20个代理的环境中,给定两个元素10000000000000000001的集合,元素10000000000000000001的值是远离00000000000000000001的1048575个索引,其在内存中是4194300个字节,其表示32767个128字节距离的cachlines。 因此,可怕的访问模式。 我试过寻找的解决方案涉及按基数/汉明重量排序索引: 基于汉明重量的索引 确定两个整数之间的字典距离 遭受算术开销,我的计算将掩盖随机访问的惩罚。 […]

C – 交换两个相同大小的内存块的最快方法?

交换两个相同大小的非重叠内存区域的最快方法是什么? 说,我需要用(t_Some *b)交换(t_Some *b) 。 考虑到时空权衡,会增加临时空间来提高速度吗? 例如, (char *tmp) vs (int *tmp) ? 我正在寻找便携式解决方案。 原型: void swap_elements_of_array(void* base, size_t size_of_element, int a, int b);

如何使用Dot产品获得峰值CPU性能?

问题 我一直在研究HPC,特别是使用矩阵乘法作为我的项目(参见我在配置文件中的其他post)。 我在那些方面取得了不错的成绩,但还不够好。 我退后一步看看我能用点积计算做得多好。 点乘积与矩阵乘法 点积更简单,我可以在不处理打包和其他相关问题的情况下测试HPC概念。 缓存阻塞仍然是一个问题,这是我的第二个问题。 算法 将两个double数组A和B n相应元素相乘并求它们。 assembly中的double点产品只是一系列movapd , mulpd , addpd 。 以巧妙的方式展开和排列,可以使movapd / mulpd / addpd组在不同的xmm寄存器上运行,因此是独立的,优化了流水线操作。 当然,事实certificate,这与我的CPU无序执行无关。 还要注意,重新安排需要剥离最后一次迭代。 其他假设 我不是在编写通用点积的代码。 代码是针对特定尺寸的,我不处理边缘情况。 这只是为了测试HPC概念并查看我可以获得的CPU使用类型。 结果 编译为gcc -std=c99 -O2 -m32 -mincoming-stack-boundary=2 -msse3 -mfpmath=sse,387 -masm=intel 。 我和平时不同的电脑。 这台计算机有一个i5 540m ,在两步Intel Turbo Boost之后, 2.8 GHz * 4 FLOPS/cycle/core = 11.2 GFLOPS/s per core可以获得2.8 GHz * […]

高速缓存内存优化数组转置:C

typedef int array[2][2]; void transpose(array dst, array src) { int i, j; for (j = 0; j < 2; j++) { for (i = 0; i < 2; i++) { dst[i][j] = src[j][i]; } } } src数组从地址0开始,dst数组从地址0x10开始。 L1数据缓存,直接映射,写分配,8字节块大小。 缓存总大小为16个数据字节。 src和dst数组的每个条目的命中或错过是什么? 答案是: src: [0][0] -> miss, [0][1] -> miss, [1][0] -> miss, [1][1] -> hit dst: […]

如何用C编写程序来测量缓存的速度?

编写程序并尝试比较(测量,如果可以)从主存和缓存访问数据的时间。 如果你能做到这一点,那么如何衡量每个级别缓存的速度?

为什么_mm_stream_ps会产生L1 / LL缓存未命中?

我正在尝试优化计算密集型算法,并且遇到了一些缓存问题。 我有一个巨大的缓冲区,偶尔写入并随机写入,并在应用程序结束时只读取一次。 显然,写入缓冲区会产生大量的缓存未命中,并且还会污染之后需要再次进行计算的缓存。 我尝试使用非时间移动instrinsics,但缓存未命中(由valgrind报告并由运行时测量支持)仍然会发生。 但是,为了进一步研究非时间动作,我写了一个小测试程序,你可以在下面看到。 顺序访问,大缓冲区,只写。 #include #include #include #include void tim(const char *name, void (*func)()) { struct timespec t1, t2; clock_gettime(CLOCK_REALTIME, &t1); func(); clock_gettime(CLOCK_REALTIME, &t2); printf(“%s : %f s.\n”, name, (t2.tv_sec – t1.tv_sec) + (float) (t2.tv_nsec – t1.tv_nsec) / 1000000000); } const int CACHE_LINE = 64; const int FACTOR = 1024; float *arr; int […]