在循环中调整内存访问
Justify Memory Access in a cycle
我有以下功能:
void ikj(float (*a)[N], float (*b)[N], float (*c)[N], int n) {
int i, j, k;
float r;
papi_start();
for (i = 0; i < n; i++) {
for (k = 0; k < n; k++) {
r = a[i][k];
for (j = 0; j < n; j++)
c[i][j] += r * b[k][j];
}
}
papi_stop();
}
我使用PAPI
来计算我在papi_start()
和papi_stop()
之间有多少加载和存储,结果如下:
负载(使用PAPI_LD_INS
):
32 26781
64 205053
128 1606077
256 12714815
512 101189551
1024 807406950
2048 6450848188
商店(使用PAPI_SR_INS
):
32 8290
64 65698
128 524578
256 4194850
512 33555490
1024 268437701
2048 2147487778
其中第一值是N的大小,第二值是指令的数量。
我使用O3进行编译,我的缓存大小为L1=32KB x 2(指令和数据,8路)和L2=1024KB(4路)(共享2个内核)。。我的cpu是英特尔T3200,有SSE3.
我知道O3优化了代码,因此它将使用预取和其他功能。由于我正在加载连续地址,并且我的缓存有64字节的行大小,我一次加载16个浮点,但我的计算没有达到这个值,所以有人能向我解释一下吗?
编辑:这是我的汇编文件,很抱歉把它们扔在这里,但我从来没有处理过汇编,我真的不能理解其中的任何一个:
http://dl.dropboxusercontent.com/u/878621/mmc.shttp://dl.dropboxusercontent.com/u/878621/mmc_asm.s
谢谢!
看看商店,你得到的数字非常接近N**3 / 4
。显然,我们期望它是O(N**3)。
这表明4个浮点写入被合并为PAPI_SR_INS正在测量的任何一个。另一种方法是计算16字节写入的次数。
类似地,负载的数量大致为3/4 N**3
。主项应该是最内部循环中来自b和c的负载,即每次迭代读取2次。老实说,我对此没有太大的理解。
如果你不知道你在测量什么,也不把它与生成的代码联系起来,那么很难预测测量结果。
EDIT:这些数字似乎与执行的加载和存储指令相关,但与L1、L2等事务或未命中的数量无关,因此不太可能与实际性能相关。时间不是一个更值得担心的数字吗?考虑到现代CPU体系结构的复杂性,我相信任何一天测量都比预测更重要。
- C++尝试深度复制唯一指针时出现内存访问冲突
- 如何使用 MPI 的远程内存访问 (RMA) 功能并行化数据聚合?
- CRTP - 危险的内存访问?
- C++ Python 的扩展 - 安全内存访问和内存布局
- 在Visual Studio中查找非法内存访问
- C++内存访问违反内存大块
- 数组中未映射的内存访问从python传递到c++
- 使用加速进程间创建消息队列 - 内存访问冲突
- C 指针转换会导致内存访问冲突
- 为什么代码会抛出非法内存访问错误
- 多线程环境中C++内存访问
- CUDA 中的递归返回非法内存访问
- 为什么创建进程 API 调用会导致内存访问冲突?
- 在 C++ 中遍历链表比在具有类似内存访问的 Go 中慢
- 确定打开进程的内存访问位置
- 存在内存访问异常,但我不确定我的代码中出了什么问题
- 指向结构的指针的 2D 数组.内存访问问题
- GPU 内存访问和使用 (CUDA)
- 在实时程序中是动态内存访问有害的
- 随机 mmaped 内存访问比堆数据访问慢 16%