所以我的老师告诉我,我应该根据需要实时计算中间结果,而不是存储它们,因为现在处理器的速度要比内存的速度快得多。
因此,当我们计算一个中间结果时,我们也需要使用一些内存,对吗?有人能给我解释一下吗?
发布于 2014-03-10 14:53:12
因此,当我们计算一个中间结果时,我们也需要使用一些内存,对吗?有人能给我解释一下吗?
一台计算机有几级内存。这些图层看起来像这样
当您使用就地计算的中间结果时,这些结果通常永远不会离开寄存器,或者可能仅限于缓存,因此不受可用系统内存带宽的限制,也不受内存总线仲裁或地址生成联锁的阻碍。
发布于 2014-03-10 14:54:03
你的老师说得对,现在处理器的速度要比内存的速度快得多,对内存的访问速度要慢得多:缓存、寄存器等。
假设您想要计算一个三角函数: sin(x)。要做到这一点,您可以调用函数(数学库提供一个函数,也可以实现自己的函数),即计算值;或者可以使用存储在内存中的查找表来获得结果,这意味着存储中间值(某种程度)。
调用一个函数将导致执行许多指令,而使用查找表则会减少指令(获取LUT地址、获取所需元素的偏移量、从address+offset读取)。In this case, storing the intermediate values is faster
但是如果要执行c = a+b,计算值要比从内存中的某个地方读取值要快得多。请注意,在这种情况下,要执行的指令数量将是相同的。
因此,虽然访问RAM的速度确实较慢,但是否值得访问RAM而不是进行计算是一个明智的问题,需要考虑以下几点:要执行的指令数,如果计算发生在一个循环中,并且可以利用架构、管道、缓存内存等。没有一个答案,您需要单独分析每一种情况。
发布于 2014-03-10 15:59:14
你的老师的建议在一个复杂的话题上过于简单化了。
如果你认为“中间”是一个术语(在单词的算术意义上),那么问问自己,你的代码是否在其他地方重复使用这个术语?也就是说,如果您的代码如下:
void calculate_sphere_parameters(double radius, double & area, double & volume)
{
area = 4 * (4 * acos(1)) * radius * radius;
volume = 4 * (4 * acos(1)) * radius * radius * radius / 3;
}你是否应该这样写:
void calculate_sphere_parameters(double radius, double & area, double *volume)
{
double quarter_pi = acos(1);
double pi = 4 * quarter_pi;
double four_pi = 4 * pi;
double four_thirds_pi = four_pi / 3;
double radius_squared = radius * radius;
double radius_cubed = radius_squared * radius;
area = four_pi * radius_squared;
volume = four_thirds_pi * radius_cubed; // maybe use "(area * radius) / 3" ?
}现代优化编译器为这两者发出相同的二进制代码并不是不可能的。我把它留给读者来决定他们喜欢在源代码中看到什么.
许多简单的算法也是如此(至少,如果计算中不涉及函数调用的话)。此外,现代编译器和/或CPU指令集可能能够免费进行“偏移”计算,例如:
for (int i = 0; i < N; i++) {
do_something_with(i, i + 25, i + 314159);
}结果将与以下内容相同:
for (int i = 0; i < N; i++) {
int j = i + 25;
int k = i + 314159;
do_something_with(i, j, k);
}因此,主要的规则应该是,如果您的代码的可读性不能通过创建一个新变量来保存“临时”计算的结果,那么使用一个变量可能是过分的。
另一方面,如果您在十行代码中使用i + 12345十几次.命名它,并评论为什么这个奇怪的硬编码偏移是如此重要。
记住,仅仅因为源代码包含一个变量,并不意味着编译器发出的二进制代码将为该变量分配内存。编译器可能会得出这样的结论:这个值甚至没有被使用(并且完全放弃了分配它的计算),或者它可能得出结论,它“只是一个中间的”(以后再也不用它从内存中检索),所以将它存储在寄存器中,在“最后一次使用”之后覆盖它。与从内存位置检索值相比,每次需要时执行类似于计算值i + 1之类的操作要有效得多。
我的建议是:
https://stackoverflow.com/questions/22303126
复制相似问题