大家一起来讨论下林锐<<高质量C++编程>>里的一个例子,该如何处理
大家一起来讨论下林锐<<高质量C++编程>>里的一个例子
在林锐的 < <高质量C++编程> > (P29)中有如下的论述:
在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU 跨切循环层的次数。例如示例4-4(b)的效率比示例4-4(a)的高。
// 4-4(a) 低效率:长循环在最外层
for (row = 0; row < 100; row++)
{
for (col = 0; col < 5; col++)
{
sum = sum + a[row][col];
}
}
// 4-4(b) 高效率:长循环在最内层
for (col = 0; col < 5; col++)
{
for (row = 0; row < 100; row++)
{
sum = sum + a[row][col];
}
}
我觉得他完全说错了,因为数组的内存分布是按行连续的.
------解决方案--------------------
for (row = 0; row < 100; row++)
{
E:
for (col = 0; col < 5; col++)
{
sum = sum + a[row][col];
}
goto E: //要跳100次
}
for (col = 0; col < 5; col++)
{
for (row = 0; row < 100; row++)
{
sum = sum + a[row][col];
} 只要5次...
}
个人理解..
------解决方案--------------------
栈
------解决方案--------------------
你只考虑了指令情况,
没考虑到 CPU 缓存。
------解决方案--------------------
兩個循環次數是一樣的
但是對 CPU 缓存影響不一樣
後者會好很多
------解决方案--------------------
我认为swimmer2000(人)有道理
就是考虑cache的处理情况
操作系统在处理数据时候并不是需要这个数据的时候只读一个数据
而是会读进一页 放入cache中
如果后面相零数据正好也在cache那么直接会从cache中访问
而不经过存储设备这样节省了时间 cache的访问速度是与寄存器几乎一个级别
b形式如果列足够大 容易造成每行读入均不命中 均要替换cache
开销增大
------解决方案--------------------
lz质疑很好,但要考虑操作系统的内存管理办法!
------解决方案--------------------
这个跟操作系统关系不大 主要是考虑高速缓存的作用
正因为数组的内存分布是按行连续的 在一个行循环内cpu跨页操作的几率较低 命中率高速度才会快
当然如果循环内比较复杂 基本可以忽略了
------解决方案--------------------
在不考虑优化的情况下,
显然就是这么个情况 ~
------解决方案--------------------
谁高谁低,还是测了才知道
------解决方案--------------------
CPU 缓存是缓存的指令,不是数据!
这个问题和数组在内存中怎么排列没关系。 因为数组是在堆栈或数据区的,而 CPU 缓存的是代码区的内容。
------解决方案--------------------
数组在堆栈或者数据区影响不大
数据区也有可能在内存区由sp计算地址和直接地址累加进行访问速度一样
那么堆栈中的数据从何而来?
//堆栈数据一是定义在函数体内,编译器分配空间时在堆栈区
还有就是函数参数入栈时分配在堆栈区
------解决方案--------------------
数组在内存排列只有当数组的列数过大
数组按行访问才会产生cache替换的这个大开销问题
取消这种机制,计算机运行速度无论怎么访问都是循环一样次数
取地址,进行计算
------解决方案--------------------
我觉得这个跟栈还有循环次数没有关系
主要还是CPU的命令缓存,如果CPU多次在一个缓存区多命令和在不同的缓存区多命令哪个快,显然是前者
------解决方案--------------------
这个,测试结果相差多少?
------解决方案--------------------
在林锐的 < <高质量C++编程> > (P29)中有如下的论述:
在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU 跨切循环层的次数。例如示例4-4(b)的效率比示例4-4(a)的高。
// 4-4(a) 低效率:长循环在最外层
for (row = 0; row < 100; row++)
{
for (col = 0; col < 5; col++)
{
sum = sum + a[row][col];
}
}
// 4-4(b) 高效率:长循环在最内层
for (col = 0; col < 5; col++)
{
for (row = 0; row < 100; row++)
{
sum = sum + a[row][col];
}
}
我觉得他完全说错了,因为数组的内存分布是按行连续的.
------解决方案--------------------
for (row = 0; row < 100; row++)
{
E:
for (col = 0; col < 5; col++)
{
sum = sum + a[row][col];
}
goto E: //要跳100次
}
for (col = 0; col < 5; col++)
{
for (row = 0; row < 100; row++)
{
sum = sum + a[row][col];
} 只要5次...
}
个人理解..
------解决方案--------------------
栈
------解决方案--------------------
你只考虑了指令情况,
没考虑到 CPU 缓存。
------解决方案--------------------
兩個循環次數是一樣的
但是對 CPU 缓存影響不一樣
後者會好很多
------解决方案--------------------
我认为swimmer2000(人)有道理
就是考虑cache的处理情况
操作系统在处理数据时候并不是需要这个数据的时候只读一个数据
而是会读进一页 放入cache中
如果后面相零数据正好也在cache那么直接会从cache中访问
而不经过存储设备这样节省了时间 cache的访问速度是与寄存器几乎一个级别
b形式如果列足够大 容易造成每行读入均不命中 均要替换cache
开销增大
------解决方案--------------------
lz质疑很好,但要考虑操作系统的内存管理办法!
------解决方案--------------------
这个跟操作系统关系不大 主要是考虑高速缓存的作用
正因为数组的内存分布是按行连续的 在一个行循环内cpu跨页操作的几率较低 命中率高速度才会快
当然如果循环内比较复杂 基本可以忽略了
------解决方案--------------------
在不考虑优化的情况下,
显然就是这么个情况 ~
------解决方案--------------------
谁高谁低,还是测了才知道
------解决方案--------------------
CPU 缓存是缓存的指令,不是数据!
这个问题和数组在内存中怎么排列没关系。 因为数组是在堆栈或数据区的,而 CPU 缓存的是代码区的内容。
------解决方案--------------------
数组在堆栈或者数据区影响不大
数据区也有可能在内存区由sp计算地址和直接地址累加进行访问速度一样
那么堆栈中的数据从何而来?
//堆栈数据一是定义在函数体内,编译器分配空间时在堆栈区
还有就是函数参数入栈时分配在堆栈区
------解决方案--------------------
数组在内存排列只有当数组的列数过大
数组按行访问才会产生cache替换的这个大开销问题
取消这种机制,计算机运行速度无论怎么访问都是循环一样次数
取地址,进行计算
------解决方案--------------------
我觉得这个跟栈还有循环次数没有关系
主要还是CPU的命令缓存,如果CPU多次在一个缓存区多命令和在不同的缓存区多命令哪个快,显然是前者
------解决方案--------------------
这个,测试结果相差多少?
------解决方案--------------------