gpt4 book ai didi

高速缓冲存储器和存储器地址

转载 作者:行者123 更新时间:2023-11-30 20:38:07 25 4
gpt4 key购买 nike

我必须做一个类的练习,我必须执行一些子例程,然后检查缓存未命中,这是附件:

我必须创建 2 个子例程,其中 s1 是 L1 缓存的容量 32kb,b1 是 64 字节的行。

subroutine A: increment all bytes of a memory buffer containing 2*s1 bytes 
in the order of increasing memory addresses;

subroutine B: increment each b1-th byte of a memory buffer containing 2*s1
bytes in the order of increasing memory addresses;

对于子例程 A,我想我只需要做:

char buffer[2*s1];  
printf...
buffer++;
printf...

两个 printf 都会显示:

buffer[0]= 0x7fff36769fe0 buffer[1]= 0x7fff36769fe1 
buffer[0]= 0x7fff36769fe1 buffer[1]= 0x7fff36769fe2

所有字节都会增加,所以,我认为这是正确的,对于子例程 B,我不知道......所以,我想为子例程 B 提供一些帮助。

如果有人能帮助我,那就太好了。

谢谢!

最佳答案

这些练习仅作为优化类(class)才有意义。不幸的是,他们并没有完全击中要害。

Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.

这是一句著名的引言,连同它的背景,出自也许是我们在这个领域可以认同的最有信誉的老师:唐纳德·高德纳 (Donald Knuth)。完成本练习后,您的教授可能会引导您分析您的未优化代码,从而向您介绍分析器

如果我们应用手动优化,就好像编译器不执行任何操作,然后才启用编译器自动优化,我们可以希望改进什么?也许编译器可能会自动执行与我们手动执行相同的优化(或更好的优化),但所需时间只占很小的一部分。

引用中的这些数字背后有一个需要考虑的营销/规划策略。在商业世界,甚至作为业余爱好者,您将花费 97% 的时间来预先开发和测试解决实际问题的程序。请注意对实际问题的强调。您不会为了观察缓存行为而编写和测试程序。您将编写和测试程序来解决现实生活中的问题

一旦您彻底编写并测试了整个程序,您就会知道它是否感觉足够快(例如,您的客户/雇主可能会告诉您对其进行优化)。如果它感觉足够快,你就不会优化它,即使到处都有缓存未命中;你甚至不知道有缓存未命中。但是,如果感觉太慢,您将需要在完全优化的代码上使用分析器来确定最重要的瓶颈在哪里,并花费大约 3% 的时间瓶颈上的时间...

乐观地编程是可能的,但这不是像这些练习那样的观察练习;这是一项计划和考虑因素的练习。一条准则是避免重复,这就是我对下面的代码所做的。通过确定两个练习之间的共同行为(例如,两个循环都从低索引到高索引,每个元素递增 1),我将两个循环减少为一个,并避免同时重复自己。考虑您的程序,尽可能避免重复,这样您的代码就会更小,从而减少测试和维护,当然也减少了重复的击键次数。 大多数的优化是对我们时间的优化,而不是对计算机时间的优化!碰巧的是,我们还通过缩小代码来优化计算机时间。

void increment_every(char *buffer, size_t multiple, size_t maximum) {
while (maximum > multiple) {
buffer[0]++;
buffer += multiple;
maximum -= multiple;
}
}

通过这个函数你应该能够解决这两个问题。例如:

#define S1 32768 /* 32KB */
#define B1 64 /* 64 B */

int main(void) {
char buffer[2 * S1] = { 0 };

increment_every(buffer, 1, sizeof buffer); // subroutine A

if (B1 < S1) { // subroutine B
increment_every(buffer + B1, B1, sizeof buffer - B1);
}
}

假设 S1B1 是固定值,并非来自文件或交互式设备。这样的假设导致编译器非常积极地进行优化。事实上,这个程序可能会优化为 int main(void) { },因为没有可观察的行为;此程序中的任何地方都没有任何文件或交互设备的输入或输出!希望您现在能在下一课中看到一些真正的教训:

  • 以最佳方式编写代码,而不是编写最佳代码。例如避免重复自己。
  • 仅在感觉太慢时才对代码进行分析。例如仅在编写并测试整个程序后才进行优化。

关于高速缓冲存储器和存储器地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30565703/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com