iPhone上的内存操作性能

时间:2009-12-21 04:26:49

标签: c iphone optimization caching

这是我用来创建不同排序数组的代码:

const unsigned int height = 1536;
const unsigned int width = 2048;

uint32_t* buffer1 = (uint32_t*)malloc(width * height * BPP);
uint32_t* buffer2 = (uint32_t*)malloc(width * height * BPP);

int i = 0;
for (int x = 0; x < width; x++)
    for (int y = 0; y < height; y++) 
        buffer1[x+y*width] = buffer2[i++];

任何人都可以解释为什么使用以下作业:

buffer1[i++] = buffer2[x+y*width];

而不是代码中的那个花费两倍的时间?

2 个答案:

答案 0 :(得分:4)

这可能取决于CPU缓存行为(12MB时,你的图像远远超过了iphone3gs内ARM Cortex A8中的256KB L2缓存)。

第一个示例按顺序访问读取数组,这很快,但必须按顺序访问写入数组,这很慢。

第二个例子恰恰相反 - 写入数组以快速,连续的顺序写入,读取数组以较慢的方式访问。在这种工作量下,写入未命中的成本明显低于读取失误。

如果你想了解更多关于此类事情的话,建议阅读Ulrich Drepper的文章What Every Programmer Should Know About Memory

请注意,如果将此操作包含在函数中,那么如果在指针参数上使用restrict限定符,则可以帮助优化器生成更好的代码,如下所示:

void reorder(uint32_t restrict *buffer1, uint32_t restrict *buffer2)
{
    int i = 0;
    for (int x = 0; x < width; x++)
        for (int y = 0; y < height; y++) 
            buffer1[x+y*width] = buffer2[i++];
}

restrict限定符向编译器承诺两个指针指向的数据不重叠 - 在这种情况下,无论如何这对于函数来说都是必要的。)

答案 1 :(得分:2)

第一个中的每个像素访问都有一个线性locality of reference,第二个像素访问会在每次读取时打开缓存,必须为每个读取主内存。

如果写入必须进入主存储器,则处理器可以更有效地处理具有错误位置的写入而不是读取,该写入可以与另一个读取/算术操作并行发生。如果读取错过了缓存,它可以完全停止处理器,等待更多数据通过缓存层次结构进行过滤。