c - 过去的手动优化(C语言)

标签 c optimization history

<分区>

回到 70 年代,当 C 刚开始时,我猜编译器级别的优化并不像现代编译器(clang、gcc 等...)那么先进,而且计算机本身在硬件方面受到限制,是否普遍喜欢在源代码级别优化可读性?

例子:

int arrayOfItems[30]; // Global variable

int GetItemAt(int index)
{
    return globalArrayOfThings[index];
}

int main()
{
    // Code
    // ... arrayOfItems intialized somewhere
    // More code

    GetSomethingByItem(GetItemAt(4)); // Get at index 4

    return 0;
}

现在可以对此进行优化:

int arrayOfItems[30]; // Global variable

int main()
{
    // Code
    // ... arrayOfItems intialized somewhere
    // More code

    GetSomethingByItem(arrayOfItems[4]); // Get at index 4

    return 0;
}

完全省略函数GetItemAt,从而通过直接从它的地址访问值而不是输入函数、创建堆栈帧、访问value 并将结果推送到某个寄存器。人们过去更喜欢将第二个“优化”版本直接写入源代码,还是使用第一个版本以使代码更具可读性?

我知道在这个例子中你可以使用处理器来“模仿”这个优化(例如 #define GetItemAt(x) arrayOfItems[x]),但你明白我的意思。

另外,也许这个确切的优化功能从一开始就存在,如果是这样,我应该再找一个例子,欢迎提出建议。

长话短说 -

  • 在过去是否更喜欢源代码级别的优化而不是可读性?

奖励问题:

  • 是否包含优化以提高源代码的可读性?

最佳答案

我认为没有多少开发人员更喜欢优化而不是可读性,但有时可能会争辩说有些优化会损害可读性但对性能来说是必要的。类似于 Duff's Device (循环展开优化)

来自

do {               /* count > 0 assumed */
  *to = *from++;   /* "to" pointer is NOT incremented, see explanation below */
} while(--count > 0);

register n = (count + 7) / 8;
switch(count % 8) {
case 0: do {    *to = *from++;
case 7:     *to = *from++;
case 6:     *to = *from++;
case 5:     *to = *from++;
case 4:     *to = *from++;
case 3:     *to = *from++;
case 2:     *to = *from++;
case 1:     *to = *from++;
    } while(--n > 0);
}

当然,事实证明编译器变得更聪明了,据 LKML 报道 removing Duff 的设备改进了 性能并减少了 内存使用。来自链接的维基百科,

For the purpose of memory-to-memory copies (which was not the original use of Duff's device, although it can be modified to serve this purpose as described in section below), the standard C library provides function memcpy; it will not perform worse than a memory-to-memory copy version of this code, and may contain architecture-specific optimizations that will make it significantly faster

来自 LKML(2000 年)

... this effect in the X server. It turns out that with branch predictions and the relative speed of CPU vs. memory changing over the past decade, loop unrolling is pretty much pointless. In fact, by eliminating all instances of Duff's Device from the XFree86 4.0 server, the server shrunk in size by half a megabyte, and was faster to boot, because the elimination of all that excess code meant that the X server wasn't thrashing the cache lines as much.

至于只提高可读性的优化,首先要求你的代码是不可读的。那么任何使它更具可读性的东西似乎都符合条件。最后,记住 premature optimization is the root of all evil .

关于c - 过去的手动优化(C语言),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27474436/

相关文章:

bash - 如何从文件加载 bash 命令历史

c - 如何获取给定名称和父目录句柄或 inode 的文件大小?

c++ - 检查数组位置 X 处的某物是否为字符

c++ - 为什么在比较范围内的数字时,汇编代码中会出现分支?

c++ - 大整数值会导致 C++ 中的性能下降?

两个时间点之间的 Bash 历史记录

zsh - 为什么我的历史记录没有保存在 zsh 选项卡之间?

c++ - 前面带 * 且返回值无效的函数声明?

c - 用 strtok() 分割字符串会出错

javascript - 如何让 TypeScript 执行尾递归优化?