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

为何在线程循环外生成大随机数矩阵比循环内逐列生成更快?

为什么三段Julia代码的性能差异这么大?

核心原因分析

第一段代码(最快)

X = randn( 3, 1000000 )
Y = Vector{Float64}( undef, 1000000 )
@threads for n in 1:size( X, 2 )
    Y[n] = do_stuff( X[:,n] )
end
  • 批量生成随机数效率拉满:randn(3, 1000000)一次性生成所有数据,底层用CPU矢量化指令批量处理,缓存利用率极高,单线程生成速度远快于多次小批量调用。
  • 并行阶段无资源竞争:并行循环仅做读取X的列、计算do_stuff、写入Y的操作。Julia默认列优先存储,X的每一列内存连续,线程读取时缓存命中率高,且各线程操作独立的列和Y元素,无锁竞争。

第二段代码(慢20%)

Y = Vector{Float64}( undef, 1000000 )
@threads for n in 1:size( X, 2 )
    X = randn( 3 )
    Y[n] = do_stuff( X )
end
  • 随机数生成的锁竞争拖后腿:全局随机数生成器(RNG)是线程安全的,但依赖内部锁实现。多个线程同时调用randn(3)时,会频繁争抢锁,导致大量等待时间,直接抵消并行的收益。
  • 小批量生成的固定开销被放大:每次仅生成3个元素,无法利用矢量化指令优势,RNG状态更新等单调用固定开销占比过高,整体生成效率远低于批量模式。

第三段代码(慢40-50%)

X = Vector{Float64}( undef, 3, 1000000 )
Y = Vector{Float64}( undef, 1000000 )
@threads for n in 1:size( X, 2 )
    X[:,n] = randn( 3 )
    Y[n] = do_stuff( X[:,n] )
end
  • 继承第二段的所有问题:同样存在RNG锁竞争和小批量生成的低效问题。
  • 额外的内存复制开销:X[:,n] = randn(3)需要把生成的3个元素复制到X的对应列,多了一次不必要的内存拷贝操作。
  • 缓存命中率进一步下降:X是大数组,多线程同时写入不同列会频繁触发缓存行刷新同步,降低内存访问效率;do_stuff(X[:,n])操作列视图时,还可能带来额外的边界检查或寻址开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 11:15:37