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

Numpy按行读取时Fortran内存布局为何比C布局执行速度更快

Numpy C顺序与Fortran顺序性能测试异常原因解析

测试结果异常的核心原因

你观测到的3秒左右的性能差异完全是测试方法设计失误导致的随机误差,并不代表F顺序行遍历速度比C顺序快:

  • 你用了三层纯Python循环做元素访问,Python本身的循环调度开销、numpy索引返回Python对象的封装开销占了总耗时的99%以上,内存访问连续性带来的性能差异被完全淹没,根本无法被观测到。
  • 你可以尝试多轮重复测试,会发现两者耗时差异完全随机,时而C快时而F快,差值波动在几秒量级,没有统计意义。

reshape的行为与flags标记的含义

首先明确两个核心事实:

  1. reshape不会主动修改内存中元素的实际存储顺序,只要新形状和原数组元素总数匹配,reshape默认会返回原内存的视图,仅修改数组的shape和stride(步长)属性。
  2. C_CONTIGUOUS和F_CONTIGUOUS标记不是直接标记内存存储顺序,而是根据数组的shape和stride计算得到的属性:
    • C连续要求:数组最后一个维度的步长等于单个元素的字节大小,行方向相邻元素在内存中相邻。
    • F连续要求:数组第一个维度的步长等于单个元素的字节大小,列方向相邻元素在内存中相邻。

你代码中的逻辑验证:

  • np.arange(1000000)生成的原始数组是C连续的,内存中元素按0、1、2...999999的顺序线性存储。
  • 当order='C'做reshape时,新数组的stride为(1000*8, 8)(假设int64类型),满足C连续的要求,因此C_CONTIGUOUS=True。
  • 当order='F'做reshape时,numpy会调整新数组的stride为(8, 1000*8),满足F连续的要求,因此F_CONTIGUOUS=True,此时内存中元素的存储顺序没有发生任何变化,只是数组的索引映射逻辑变了。

正确的性能测试方法

要观测内存连续性带来的性能差异,需要排除Python层面的开销,使用numpy底层实现的向量化操作即可:

import numpy as np
import time

x_c = np.arange(1000000).reshape((1000, 1000), order='C')
x_f = np.arange(1000000).reshape((1000, 1000), order='F')

# 测试按行求和(行遍历)
start = time.time()
np.sum(x_c, axis=1)
print(f"C顺序行求和耗时: {time.time() - start}")

start = time.time()
np.sum(x_f, axis=1)
print(f"F顺序行求和耗时: {time.time() - start}")

运行后可以看到C顺序行遍历的速度是F顺序的数倍,完全符合我们的认知。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:18:03