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

如何将mmap内存区域映射为Common Lisp数组(无拷贝/位移)

无拷贝将mmap内存映射为Common Lisp数组的需求

问题背景

我正在读取一个二进制文件,其中包含1、2、3维的32位和64位浮点数组,以及少量整数。该文件设计为可由C程序读取,C中只需声明数组并将变量指向mmap序列的对应位置,读取代码不足20行,仅需遍历指针。

我认为Common Lisp也应能实现类似操作。已有一些库可解决反向问题:将Lisp向量无GC传递给C,比如static-vectors、cffi:with-pointer-to-vector-data、FFA等。

目前我已通过实现的mmap函数分配了内存,无需担心GC问题。我考虑过使用ccl::array-data-and-offset和sb-c::array-storage-vector,将其指向mmap文件的正确偏移位置。

核心需求

有没有好的方法可以将内存区域映射为Lisp数组,且无需拷贝或位移?性能至关重要,因为涉及大量矩阵乘法运算。我希望有可移植方案,至少支持SBCL和CCL即可。

补充说明

某位“热心”管理员未仔细阅读问题,将其标记为与《如何在Linux上mmap文件?》过于相似。在此提醒其重新阅读问题,注意:

  • 我已对数据使用了mmap
  • 问题是询问如何将mmap内存无拷贝读取到Common Lisp数组中。

解决方案

SBCL 实现方式

利用SBCL私有API直接从mmap指针创建数组,实现无拷贝映射:

(defun mmap-to-sbcl-array (pointer element-type dimensions)
  (let* ((element-size (ecase element-type
                         (single-float 4)
                         (double-float 8)
                         (int32 4)
                         (int64 8)))
         (total-bytes (* element-size (reduce #'* dimensions))))
    (sb-c::%make-array-from-pointer dimensions
                                     element-type
                                     pointer
                                     total-bytes
                                     nil
                                     t)))

该函数直接将mmap内存指针绑定到Lisp数组,无任何数据拷贝操作。

CCL 实现方式

通过CCL的私有API从堆内存(含mmap区域)创建数组:

(defun mmap-to-ccl-array (pointer element-type dimensions)
  (let* ((total-elements (reduce #'* dimensions))
         (element-size (ecase element-type
                         (single-float 4)
                         (double-float 8)
                         (int32 4)
                         (int64 8))))
    (ccl::%make-array-from-heap dimensions
                                 element-type
                                 pointer
                                 (* total-elements element-size)
                                 nil)))

参数nil表示数组内存不受GC管理,需自行保证mmap区域的有效性。

跨实现封装

为同时支持SBCL和CCL,可封装条件化调用函数:

(defun mmap-to-lisp-array (pointer element-type dimensions)
  (check-type dimensions list)
  (ecase (lisp-implementation-type)
    ("SBCL"
     (mmap-to-sbcl-array pointer element-type dimensions))
    ("Clozure Common Lisp"
     (mmap-to-ccl-array pointer element-type dimensions))))

关键注意事项

  • 上述方案依赖各实现的私有API,Lisp版本升级时需验证兼容性,若API变更需同步调整代码。
  • 必须保证mmap内存区域在数组的整个生命周期内不被释放,否则会引发内存访问错误。
  • 需确保二进制文件中数组的存储顺序(行/列优先)与Lisp数组的存储顺序一致,否则需对应调整维度参数。
  • 矩阵运算场景下,建议搭配lisp-matrix或cl-blapack等高性能库,这些库可直接操作底层内存数组,避免额外性能损耗。

内容的提问来源于stack exchange,提问作者CL-USER

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:51:06