You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何D语言中相同for循环第二次运行速度更快?

为啥连续两个一模一样的for循环,第二个总是跑得更快?

嘿,你碰到的这个现象其实是**CPU缓存预热(Cache Warming)**搞的鬼,这是硬件层面的通用性能逻辑,和你在对比的D语言内置数组、普通指针没啥直接关系,咱们来拆解清楚:

先把你的代码补全方便理解

我先把你没写完的代码补全(推测你是在做内存读写的性能测试):

import std.stdio : writeln;
import std.datetime : StopWatch;
import core.stdc.stdlib : malloc, free;

void main() {
    immutable N = 1_000_000_000;
    StopWatch sw;
    uint* ptr = cast(uint*)malloc(uint.sizeof * N);
    
    // 第一个测试循环
    sw.start();
    for (uint i = 0; i < N; ++i) {
        ptr[i] = i; // 不管是读还是写,逻辑一致
    }
    sw.stop();
    writeln("第一个循环耗时: ", sw.peek());
    
    // 重置计时器,跑第二个完全相同的循环
    sw.reset();
    sw.start();
    for (uint i = 0; i < N; ++i) {
        ptr[i] = i;
    }
    sw.stop();
    writeln("第二个循环耗时: ", sw.peek());
    
    free(ptr);
}

背后的核心原因:CPU缓存机制

CPU的运算速度比主存快好几个数量级,所以硬件设计了多级缓存(L1、L2、L3)来缩小这个差距:

  • 第一次循环的时候:你要访问的内存块还没被加载到CPU缓存里,每一次内存读写都会触发「缓存缺失」——CPU得停下来等数据从慢得要死的主存加载到缓存,这个过程要花几十甚至几百个CPU周期,自然耗时久。
  • 第二次循环的时候:经过第一次循环的“折腾”,目标内存区域已经被完整加载到CPU缓存里了,此时所有的内存访问都是「缓存命中」,速度是缓存级别的(仅几个CPU周期),所以整体耗时直接砍半甚至更少。

怎么验证这个结论?

你可以试试这几个小实验:

  • 交换两个循环的顺序:先跑原来的第二个循环,再跑第一个,你会发现原来慢的那个现在变快了,顺序一变结果就反转,说明问题完全在缓存,不在循环本身。
  • 提前预热缓存:在正式计时前先跑一次无计时的循环,再开始测,两次计时的结果会变得差不多。
  • 换块新内存:第二个循环去访问另一块malloc出来的全新内存,此时第二个循环也会变慢,因为新内存没被缓存过。

和D语言数组/指针的关系

别担心,这不是D语言的问题——不管你用D的内置数组uint[] arr = new uint[N];还是用C风格的malloc指针,只要是连续访问同一块内存,都会出现第二次循环更快的情况,这是所有现代CPU都有的特性,和语言无关。

内容的提问来源于stack exchange,提问作者Betelgeyser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:55:59