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

如何在Common Lisp中实现表单并行执行?类似并行PROGN的方案

解决方案

你的需求本质是并行执行一系列无依赖、无共享修改冲突的独立语句,lparallel完全可以通过「将每个赋值操作包装为匿名函数,批量调度执行」来实现,具体步骤如下:

1. 初始化线程池(可选,首次使用时执行)

先根据你的CPU核心数创建线程池,后续所有并行任务都会在这里调度:

(lparallel:make-kernel 4) ; 示例:创建4个工作线程,可根据硬件调整

2. 包装赋值语句为任务函数

将每一条incf语句封装成无参匿名函数,因为formula是编译时生成的表达式,这些lambda会在编译阶段直接展开对应的计算逻辑,不会引入额外运行时开销:

;; 假设原语句是这些
(incf (aref res 1) formula1)
(incf (aref res 2) formula2)
(incf (aref res 3) formula3)

;; 包装为任务列表
(defparameter *parallel-tasks*
  (list
   (lambda () (incf (aref res 1) formula1))
   (lambda () (incf (aref res 2) formula2))
   (lambda () (incf (aref res 3) formula3))
   ;; ... 追加所有其他赋值任务
   ))

3. 并行执行所有任务

使用lparallel提供的批量任务执行函数,直接调度所有任务到线程池并行运行:

方法一:用pmapcar(通用方式)

通过funcall调用每个任务函数,pmapcar会自动分配到不同线程执行,直到所有任务完成:

(lparallel:pmapcar #'funcall *parallel-tasks*)

方法二:用run-tasks(更贴合无返回值场景)

如果不需要任务的返回值,run-tasks是更轻量的选择,专门用于执行无返回的并行任务:

(lparallel:run-tasks *parallel-tasks*)

关键注意事项

  • 因为每个数组索引仅被一个任务修改,不存在多线程竞争,所以不需要额外加锁,完全线程安全。
  • 线程池只需初始化一次,后续可以重复使用;如果需要关闭线程池,执行(lparallel:end-kernel)即可。
  • 这种方式完全适配编译时生成的formula表达式,lambda会在编译阶段将formula的逻辑内联,不会影响计算效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 16:22:11