我正在进行内存访问实验,其中使用了2D矩阵,每行都是内存页面的大小。该实验包括使用行/列主要读取每个元素,然后使用行/列主要写入每个元素。正在访问的矩阵是使用全局范围声明的,以简化编程要求。
这个问题的关键是,在静态声明测试矩阵的情况下,编译器将值初始化为零,我发现的结果非常有趣。当我首先读取操作时,即
rowMajor_read();
colMajor_read();
rowMajor_write();
colMajor_write();
然后我的colMajor_read操作很快就完成了。
但是,如果我在阅读之前进行写操作,我们有:
rowMajor_write();
colMajor_write();
rowMajor_read();
colMajor_read();
并且列主要读取操作增加了近一个数量级。
我认为它必须与编译器如何优化代码有关。由于每个元素的全局矩阵都相同,编译器是否完全删除了读取操作?或者它是某种方式"更容易"从内存读取一个相同为零的值?
我没有针对优化传递任何特殊的编译器命令,但我确实以这种方式声明了我的函数。
inline void colMajor_read(){
register int row, col;
register volatile char temp __attribute__((unused));
for(col = 0; col < COL_COUNT; col++)
for(row = 0; row < ROW_COUNT; row++)
temp = testArray[row][col];
}
因为我遇到了编译器从上面的函数中完全删除temp
变量的问题,因为它从未被使用过。我认为同时拥有volatile
和__attribute__((unused))
是多余的,但我还是将其包括在内。我的印象是没有对volatile变量实现优化。
有什么想法吗?
我查看了生成的程序集,结果与colMajor_read函数的结果相同。 (汇编)非内联版本:http://pastebin.com/C8062fYB
答案 0 :(得分:7)
在将值写入矩阵之前和之后检查进程的内存使用情况。例如,如果它存储在Linux上的.bss部分中,则归零页面将映射到具有写时复制语义的单个只读页面。因此,即使您正在阅读一堆地址,您也可能一遍又一遍地阅读同一页物理内存。
此页面http://madalanarayana.wordpress.com/2014/01/22/bss-segment/有一个很好的解释。
如果是这种情况,那么之后再次将矩阵归零并重新运行读取测试,它应该不再那么快。