在循环中调整内存访问

Justify Memory Access in a cycle

本文关键字:内存 访问 调整 循环      更新时间:2023-10-16

我有以下功能:

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体系结构的复杂性,我相信任何一天测量都比预测更重要。