4

我有以下功能:

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 是 Intel T3200 和有SSE3..

我知道 O3 优化了代码,因此它将在其他功能中使用预取,并且由于我正在加载连续地址并且我的缓存有 64 字节的行大小,我一次加载 16 个浮点数,但我的计算没有达到这个价值观,所以有人可以向我解释一下吗?

编辑:这是我的汇编文件,很抱歉把它们扔在这里,但我从未使用过汇编,我无法真正理解其中的任何一个:

http://dl.dropboxusercontent.com/u/878621/mmc.s http://dl.dropboxusercontent.com/u/878621/mmc_asm.s

谢谢!

4

1 回答 1

3

看看商店,你得到的数字非常接近N**3 / 4。显然,我们希望它是 O(N**3)。

这表明 4 个浮点写入被合并到 PAPI_SR_INS 正在测量的任何一个中。或者看看它,你正在计算 16 字节写入的数量。

同样,负载的数量大致为3/4 N**3。主要项应该是最内层循环内来自 b 和 c 的负载,每次迭代读取 2 次。老实说,我无法理解这一点。

如果您不确切知道您正在测量什么,并且您不将其与生成的代码相关联,那么很难预测测量结果。

编辑:这些数字似乎与执行的加载和存储指令相关,但与 L1、L2 等事务或未命中的数量无关——因此不太可能与实际性能相关。花费的时间不是更值得担心的数字吗?鉴于现代 CPU 架构的复杂性,我相信任何一天的测量都胜过预测。

于 2013-12-08T16:58:49.877 回答