【问题标题】:Performance of memory operations on iPhoneiPhone上内存操作的性能
【发布时间】:2010-12-28 15:11:35
【问题描述】:

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

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];

而不是我的代码中的那个需要两倍的时间?

【问题讨论】:

  • 不同内存页之间跳转?与您在算法类中假设的不同,内存访问不是恒定时间操作,尽管您可能可以为给定架构设置上限。
  • 几个问题:首先,您是在调试还是发布版本进行测试。第二,你是如何确定时机的?
  • 代码段的汇编输出是什么?这听起来像是建筑废话,除非我遗漏了一些明显的东西。
  • 尝试宽度和高度,例如 ... 100,看看是否有任何差异。
  • 你用的是什么编译器?什么优化级别?你能把乘法从内部循环中取出来吗?

标签: c iphone optimization caching


【解决方案1】:

这可能与 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 限定符向编译器保证两个指针所指向的数据不会重叠——在这种情况下,这对于函数有意义是必要的)。

【讨论】:

    【解决方案2】:

    第一个中的每个像素访问都有一个线性的locality of reference,第二个在每次读取时都会破坏您的缓存,而每次读取都必须转到主内存。

    处理器可以比读取更有效地处理局部性不好的写入,如果写入必须进入主内存,则写入可以与另一个读取/算术操作并行发生。如果读取未命中缓存,它可能会完全停止处理器等待更多数据通过缓存层次结构进行过滤。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-15
      • 2011-01-16
      • 1970-01-01
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-21
      • 1970-01-01
      相关资源
      最近更新 更多