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

如何在不加载全量数据时将内存映射Numpy数组转为Fortran顺序?

如何在不加载全量数据的情况下将C顺序内存映射Numpy数组转为Fortran顺序

我通过内存映射加载了一个超出内存容量的Numpy数组:

arr = np.load("a.npy", mmap_mode='r')

后续计算需要将它转为Fortran顺序,但使用np.asfortranarray转换后调用np.save会把整个数组加载到内存,内存占用与输入数据成正比。我需要实现纯文件到文件的操作,怎么才能在不加载全量数据的前提下完成转换?

示例说明

假设原数组为:

arr = np.array([[1, 2],
                [3, 4]])

它在磁盘上以C顺序存储:

fortran_order: False
01 02 03 04

不同转换方式的结果对比:

  1. 直接调用np.asfortranarray(arr)后保存:

    np.asfortranarray(arr)
    # 输出:
    array([[1, 2],
           [3, 4]])
    

    磁盘存储变为Fortran顺序,数据排列符合需求:

    fortran_order: True
    01 03 02 04
    但该方式会将全量数据加载到内存,无法处理超大型数组。

  2. 调用np.asfortranarray(arr.T)后保存:

    np.asfortranarray(arr.T)
    # 输出:
    array([[1, 3],
           [2, 4]])
    

    磁盘存储:

    fortran_order: True
    01 02 03 04
    数据排列未发生实质变化,不符合需求。

  3. 直接保存arr.T:

    arr.T
    # 输出:
    array([[1, 3],
           [2, 4]])
    

    磁盘存储:

    fortran_order: True
    01 02 03 04
    arr.T仅改变数组的访问视图,并未修改磁盘上的数据存储顺序,同样不符合需求。

解决方案:分块处理+内存映射写入

核心思路是分块读取原C顺序数组的连续块,按Fortran顺序的连续块写入目标文件,全程仅加载小块数据到内存。

步骤1:创建Fortran顺序的内存映射目标数组

先读取原数组的元数据(形状、数据类型等),不加载实际数据,然后创建对应规格的Fortran顺序内存映射文件:

import numpy as np

# 读取原数组元信息
with np.load("a.npy", mmap_mode='r') as arr:
    src_shape = arr.shape
    src_dtype = arr.dtype

# 创建Fortran顺序的内存映射目标数组
target_arr = np.lib.format.open_memmap(
    "a_fortran.npy",
    mode='w+',
    dtype=src_dtype,
    shape=src_shape,
    order='F'
)

步骤2:分块读写数据

根据可用内存设置合适的块大小,分块读取原数组的连续区域,写入目标数组的对应位置。以二维数组为例,按列分块处理:

block_size = 1024  # 根据可用内存调整,比如设为内存能容纳的最大列数

with np.load("a.npy", mmap_mode='r') as arr:
    # 遍历原数组的列,分块处理
    for col_start in range(0, src_shape[1], block_size):
        col_end = min(col_start + block_size, src_shape[1])
        # 读取原数组的当前列块(C顺序下arr[:, col_start:col_end]是连续内存)
        block = arr[:, col_start:col_end]
        # 将块写入目标数组的对应列(Fortran顺序下target_arr[:, col_start:col_end]是连续内存)
        target_arr[:, col_start:col_end] = block

步骤3:收尾操作

显式删除内存映射对象,确保数据写入磁盘:

del target_arr

原理说明

  • 原数组是C顺序,arr[:, col_start:col_end]对应磁盘上的连续数据块,读取时仅加载该块到内存。
  • 目标数组是Fortran顺序,target_arr[:, col_start:col_end]对应磁盘上的连续数据块,写入时直接按Fortran顺序存储。
  • 分块处理将内存占用控制在块大小范围内,避免加载全量数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:50:20