Arraymancer

GitHub
1.4k 100 较难 1 次阅读 1周前Apache-2.0视频开发框架
AI 解读 由 AI 自动生成,仅供参考

Arraymancer 是一个基于 Nim 语言开发的高性能、易用且可移植的张量(多维数组)库,专为科学计算与深度学习打造。它旨在解决传统方案中速度与开发效率难以兼得的痛点:既拥有接近 C++ 的运行时性能,又凭借 Nim 语言极快的编译速度,让原型开发比 C++ 更加敏捷高效。

该工具支持 CPU、GPU 及嵌入式设备,通过 OpenMP、CUDA 和 OpenCL 后端实现灵活加速,功能覆盖从基础数值计算到机器学习(如分类、回归、聚类)及深度学习的完整生态。其设计灵感源自 Python 社区的 NumPy 和 PyTorch,但提供了更强的类型安全与执行效率。

Arraymancer 特别适合追求高性能计算的科研人员、算法工程师以及系统开发者使用。如果你需要在资源受限的嵌入式环境部署模型,或希望在不牺牲执行速度的前提下快速验证复杂的数学算法,这是一个理想选择。此外,它还允许开发者按需组合底层线性代数库(如 BLAS、LAPACK、MKL),为构建定制化的科学计算生态系统提供了坚实基础。

使用场景

某嵌入式视觉团队需要在资源受限的工业相机上部署实时缺陷检测模型,同时保持算法迭代的高效性。

没有 Arraymancer 时

  • 开发效率低下:团队被迫在 Python 中验证算法后,用 C++ 重写底层张量运算以适配嵌入式环境,双重维护导致原型验证周期长达数周。
  • 硬件适配困难:缺乏统一的后端抽象,针对 CPU、GPU 或特定嵌入式加速器(如 OpenCL 设备)需分别编写异构代码,移植成本极高。
  • 性能与体积失衡:引入重型深度学习框架会导致内存占用超标,而手动优化 BLAS/LAPACK 调用又极易出错,难以在有限算力下达成实时推理。
  • 编译等待漫长:C++ 项目每次修改底层矩阵逻辑都需要漫长的重新编译时间,严重阻碍了参数调优和实验频率。

使用 Arraymancer 后

  • 单一语言全流程:利用 Nim 语言特性,团队直接用 Arraymancer 完成从数据预处理、PCA 降维到模型训练的全流程,无需跨语言重写,原型落地缩短至数天。
  • 后端无缝切换:通过简单的编译标志(如 -d:cuda-d:opencl),同一份张量代码即可在服务器 GPU 上训练,并平滑部署到嵌入式设备的 OpenCL 加速器上。
  • 极致性能控制:Arraymancer 提供类似 NumPy 的 ergonomics,却生成原生机器码;结合 -d:danger 移除边界检查及自定义 BLAS 库,在极小内存占用下实现毫秒级推理。
  • 秒级编译迭代:得益于 Nim 的极速编译能力,即使修改底层张量操作,整个项目也能在 5 秒内完成构建,让工程师能高频次尝试新的算法策略。

Arraymancer 让开发者在享受脚本语言般开发体验的同时,获得了足以驾驭嵌入式边缘计算的原生性能与跨平台灵活性。

运行环境要求

操作系统
  • Linux
  • macOS
  • Windows
GPU
  • 非必需
  • 支持 NVIDIA GPU (需 CUDA 后端) 或 OpenCL 设备
  • 若启用 CUDA 需安装 CUDA Toolkit 和可选的 CuDNN
  • 具体版本未说明,由用户编译时通过 `-d:cuda` 标志决定
内存

未说明

依赖
notes1. 该工具基于 Nim 语言,不使用 Python。2. 必须安装 BLAS 和 LAPACK 线性代数库(Windows 需手动下载 dll,macOS 自带 Accelerate 框架,Linux 可通过包管理器安装)。3. 推荐使用 choosenim 安装 Nim,并通过 nimble 安装本库。4. 支持通过编译标志 (-d:openmp, -d:cuda, -d:avx512 等) 定制后端和优化指令集。5. 项目状态标记为“实验性”(experimental)。
python不需要 (基于 Nim 语言)
Nim 编译器
BLAS 库 (如 OpenBLAS, MKL, Apple Accelerate)
LAPACK 库
Arraymancer hero image

快速开始

加入Discord #nim-science聊天 Github Actions CI License Stability

Arraymancer - 一个N维张量(ndarray)库。

Arraymancer是用Nim编写的张量(N维数组)项目。其主要目标是提供一个快速且易用的CPU、Cuda和OpenCL ndarray库,以此为基础构建科学计算生态系统。 该库受到NumPy和PyTorch的启发,适用于以下场景:

  • 用于数值计算的N维数组(张量)
  • 机器学习算法(如Scikit-learn中的最小二乘法求解器、PCA与降维、分类器、回归器和聚类算法、交叉验证等)
  • 深度学习

ndarray组件可以独立于机器学习和深度学习部分使用。它还支持OpenMP、Cuda或OpenCL后端。

注意:虽然Nim是编译型语言,目前尚不提供像Jupyter那样的交互式REPL,但由于其极快的编译速度,相比C++能够实现更快的原型开发。在我双核MacBook上,Arraymancer大约5秒即可完成编译。

支持的编译标志说明:

  • -d:release:Nim发布模式(无堆栈跟踪和调试信息)
  • -d:danger:禁用运行时检查,如数组越界检查
  • -d:blas=blaslibname:自定义Arraymancer使用的BLAS库。默认情况下(即未设置此选项时),Arraymancer会尝试在系统路径中自动查找BLAS库(例如blas.so/blas.dlllibopenblas.dll)。只有在需要使用特定BLAS库时才应设置此选项。更多信息请参见nimblas
  • -d:lapack=lapacklibname:自定义Arraymancer使用的LAPACK库。默认情况下(即未设置此选项时),Arraymancer会尝试在系统路径中自动查找LAPACK库(例如lapack.so/lapack.dlllibopenblas.dll)。只有在需要使用特定LAPACK库时才应设置此选项。更多信息请参见nimlapack
  • -d:openmp:多线程编译
  • -d:mkl:已弃用的标志,强制使用MKL。同时隐含-d:openmp。建议改用-d:blas=mkl -d:lapack=mkl,但仅当您希望强制Arraymancer使用MKL而非自动查找可用的BLAS/LAPACK库时才适用。
  • -d:openblas:已弃用的标志,强制使用OpenBLAS。建议改用-d:blas=openblas -d:lapack=openblas,但仅当您希望强制Arraymancer使用OpenBLAS而非自动查找可用的BLAS/LAPACK库时才适用。
  • -d:cuda:启用Cuda支持进行编译
  • -d:cudnn:启用CuDNN支持,同时隐含-d:cuda
  • -d:avx512:通过向gcc/clang传递-mavx512dq标志来启用AVX512支持。若不使用此标志,即使CPU支持AVX512,生成的二进制文件也不会利用该指令集。然而,启用此标志会使二进制文件无法在不支持AVX512的CPU上运行。相关讨论请参见#505(来自v0.7.9版本)。
  • 安装完成后,您可能需要调整nim.cfg中的库路径,以便进行OpenBLAS、MKL和Cuda编译。 当前的默认设置在Mac和Linux上应该可以正常工作;而在Windows上,则需下载libopenblas.dll或其他BLAS/LAPACK DLL(详见“安装”章节),并将其复制到系统路径中的某个文件夹或编译输出目录中。

给我看看代码吧

Arraymancer教程可在这里找到。

以下是Arraymancer语法的一个预览。

张量创建与切片

import math, arraymancer

const
    x = @[1, 2, 3, 4, 5]
    y = @[1, 2, 3, 4, 5]

var
    vandermonde = newSeq[seq[int]]()
    row: seq[int]

for i, xx in x:
    row = newSeq[int]()
    vandermonde.add(row)
    for j, yy in y:
        vandermonde[i].add(xx^yy)

let foo = vandermonde.toTensor()

echo foo

# Tensor[system.int] of shape "[5, 5]" on backend "Cpu"
# |1          1       1       1       1|
# |2          4       8      16      32|
# |3          9      27      81     243|
# |4         16      64     256    1024|
# |5         25     125     625    3125|

echo foo[1..2, 3..4] # slice

# Tensor[system.int] of shape "[2, 2]" on backend "Cpu"
# |16      32|
# |81     243|

echo foo[_|-1, _] # reverse the order of the rows

# Tensor[int] of shape "[5, 5]" on backend "Cpu"
# |5      25      125     625     3125|
# |4      16       64     256     1024|
# |3       9       27      81      243|
# |2       4        8      16       32|
# |1       1        1       1        1|

重塑与拼接

import arraymancer, sequtils

let a = toSeq(1..4).toTensor.reshape(2,2)

let b = toSeq(5..8).toTensor.reshape(2,2)

let c = toSeq(11..16).toTensor
let c0 = c.reshape(3,2)
let c1 = c.reshape(2,3)

echo concat(a,b,c0, axis = 0)
# Tensor[system.int] of shape "[7, 2]" on backend "Cpu"
# |1      2|
# |3      4|
# |5      6|
# |7      8|
# |11    12|
# |13    14|
# |15    16|

echo concat(a,b,c1, axis = 1)
# Tensor[system.int] of shape "[2, 7]" on backend "Cpu"
# |1      2     5     6    11    12    13|
# |3      4     7     8    14    15    16|

广播

图片来自Scipy

import arraymancer

let j = [0, 10, 20, 30].toTensor.reshape(4,1)
let k = [0, 1, 2].toTensor.reshape(1,3)

echo j +. k
# Tensor[system.int] of shape "[4, 3]" on backend "Cpu"
# |0      1     2|
# |10    11    12|
# |20    21    22|
# |30    31    32|

一个简单的两层神经网络

摘自示例3

import arraymancer, strformat

discard """
一个具有单个隐藏层的全连接ReLU网络,通过最小化欧几里得距离的平方来训练预测y从x。
"""

# ##################################################################
# 环境变量

# N是批量大小;D_in是输入维度;
# H是隐藏维度;D_out是输出维度。
let (N, D_in, H, D_out) = (64, 1000, 100, 10)

# 创建将保存计算图的自动微分上下文
let ctx = newContext Tensor[float32]

# 创建随机张量作为输入和输出,并将其包装为Variable。
let
  x = ctx.variable(randomTensor[float32](N, D_in, 1'f32))
  y = randomTensor[float32](N, D_out, 1'f32)

# ##################################################################

# 定义模型

网络 TwoLayersNet:
  层:
    fc1: 线性(D_in, H)
    fc2: 线性(H, D_out)
  前向传播 x:
    x.fc1.relu.fc2

让
  模型 = 上下文.初始化(TwoLayersNet)
  优化器 = 模型.优化器(SGD, 学习率 = 1e-4'f32)

# ##################################################################
# 训练

对于 t 在 0 ..< 500:
  让
    y_pred = 模型.前向传播(x)
    损失 = y_pred.mse_loss(y)

  打印 &"第 {t} 轮:损失 {loss.value[0]}"

  损失.反向传播()
  优化器.更新()

预告 使用 Arraymancer 的循环神经网络生成的文本

来自 示例 6

在我的笔记本电脑 CPU 上训练了 45 分钟,生成了 4000 个字符

威瑟!
仆人封印着,只做出些卑鄙的猜测,
他们不过是那些一直对我不忠的人;
你的戏码让王后的妻子看到了错误的部分
带着一个奇怪、可怜又可怕的冷酷的孩子
罪犯们会如何评价你的角色呢?我,王子!
现在不是没有牙齿的时候:
你对此只是肮脏而已。
我和伙伴们打破了我的复仇,所以,以及他的历史
就像你们这些领主一样,或者说是港口的真正盐分。

罗密欧:
你已经发誓要保护自己,并且正在谈论他们;她是不是被你的胆汁谋杀了?

# [...] 查看示例 6 获取完整的文本生成样本

目录

安装

Nim 在一些 Linux 发行版的软件仓库中以及 macOS 的 Homebrew 中都可以找到。

不过,我建议通过 choosenim 将 Nim 安装到您的用户目录中。一旦使用 choosenim 安装了 Nim,您就可以运行 nimble install arraymancer,这将下载最新的 Arraymancer 版本及其所有依赖项。

如果您想安装 Arraymancer 的开发版本,可以使用 nimble install arraymancer@#head

Arraymancer 需要 BLAS 和 LAPACK 库。

  • 在 Windows 上,您可以从 OpenBLAS 网站的二进制包部分获取 OpenBLAS 库,它将 BLAS 和 LAPACK 合并为一个 DLL 文件(libopenblas.dll)。或者,您也可以从 LAPACK for Windows 网站单独下载 BLAS 和 LAPACK 库。然后,您需要将这些 DLL 文件复制或解压到您的系统路径中的某个文件夹,或者放到包含编译目标的文件夹中。
  • 在 macOS 上,Apple Accelerate Framework 已经包含在所有 macOS 版本中,提供了这些库。
  • 在 Linux 上,您可以使用包管理器下载 libopenblas 和 liblapack。

Windows 用户可能需要从 openblas 的二进制发布部分下载 libopenblas.dll,将其解压到编译

完整文档

详细的 API 文档可在 Arraymancer 官方 文档 中找到。注意:此文档仅针对 0.X 版本生成。请查看 示例文件夹 以了解最新的开发进展。

特性

目前,Arraymancer 主要处于多维数组阶段,具体来说,Arraymancer 提供以下功能:

  • 基本数学运算推广到张量(sin、cos 等)
  • 矩阵代数原语:矩阵-矩阵、矩阵-向量乘法
  • 简单高效的切片操作,包括使用范围和步长
  • 无需担心“矢量化”操作
  • 支持广播。与 NumPy 不同,它是显式的,您只需使用 +. 而不是 +
  • 丰富的重塑操作:拼接、重塑、拆分、分块、排列、转置
  • 支持最多 6 维的张量。例如,4 部 3D RGB 微电影,每部 10 秒,就是 6 维: [4, 10, 3, 64, 1920, 1080] 对应 [影片数量、时间、颜色、深度、高度、宽度]
  • 可以读取和写入 .csv、Numpy (.npy) 和 HDF5 文件
  • OpenCL 和 CUDA 加速的张量(目前功能不如 CPU 张量丰富)
  • 协方差矩阵
  • 特征值和特征向量分解
  • 最小二乘法求解器
  • K-means 和 PCA(主成分分析)

Arraymancer 作为深度学习库

深度学习功能目前仍可探索,但被认为不稳定,因为我还在完善其最终接口。

提醒:最终接口仍在 开发中

您还可以观看以下动画版 神经网络演示,该演示展示了通过 nim-plotly 进行的实时训练。

Fizzbuzz 用全连接层(也称为密集层、仿射层或线性层)

神经网络定义摘自 示例 4

导入 arraymancer

常量
  数字位数 = 10
  隐藏层节点数 = 100

网络 FizzBuzzNet:
  层:
    隐藏层: 线性(数字位数, 隐藏层节点数)
    输出层: 线性(隐藏层节点数, 4)
  前向传播 x:
    x.隐藏层.relu.输出层

让
  上下文 = 新建上下文 Tensor[float32]
  模型 = 上下文.初始化(FizzBuzzNet)
  优化器 = 模型.优化器(SGD, 0.05'f32)
# ....
打印答案
# @["1", "2", "fizz", "4", "buzz", "6", "7", "8", "fizz", "10",

#   "11", "12", "13", "14", "15", "16", "17", "fizz", "19", "buzz",
#   "fizz", "22", "23", "24", "buzz", "26", "fizz", "28", "29", "30",
#   "31", "32", "fizz", "34", "buzz", "36", "37", "38", "39", "40",
#   "41", "fizz", "43", "44", "fizzbuzz", "46", "47", "fizz", "49", "50",
#   "fizz", "52","53", "54", "buzz", "56", "fizz", "58", "59", "fizzbuzz",
#   "61", "62", "63", "64", "buzz", "fizz", "67", "68", "fizz", "buzz",
#   "71", "fizz", "73", "74", "75", "76", "77","fizz", "79", "buzz",
#   "fizz", "82", "83", "fizz", "buzz", "86", "fizz", "88", "89", "90",
#   "91", "92", "fizz", "94", "buzz", "fizz", "97", "98", "fizz", "buzz"]

使用卷积的手写数字识别

神经网络定义摘自示例 2

import arraymancer

network DemoNet:
  layers:
    cv1:        Conv2D(@[1, 28, 28], out_channels = 20, kernel_size = (5, 5))
    mp1:        Maxpool2D(cv1.out_shape, kernel_size = (2,2), padding = (0,0), stride = (2,2))
    cv2:        Conv2D(mp1.out_shape, out_channels = 50, kernel_size = (5, 5))
    mp2:        MaxPool2D(cv2.out_shape, kernel_size = (2,2), padding = (0,0), stride = (2,2))
    fl:         Flatten(mp2.out_shape)
    hidden:     Linear(fl.out_shape[0], 500)
    classifier: Linear(500, 10)
  forward x:
    x.cv1.relu.mp1.cv2.relu.mp2.fl.hidden.relu.classifier

let
  ctx = newContext Tensor[float32] # 自动求导/神经网络图
  model = ctx.init(DemoNet)
  optim = model.optimizer(SGD, learning_rate = 0.01'f32)

# ...
# 在笔记本电脑的 CPU 上,几分钟内准确率就能超过 90%

使用堆叠循环神经网络进行序列分类

神经网络定义摘自示例 5

import arraymancer

const
  HiddenSize = 256
  Layers = 4
  BatchSize = 512


network TheGreatSequencer:
  layers:
    gru1: GRULayer(1, HiddenSize, 4) # (输入特征数, 隐藏层大小, 堆叠层数)
    fc1: Linear(HiddenSize, 32)                  # 每个 GRU 层一个分类器
    fc2: Linear(HiddenSize, 32)
    fc3: Linear(HiddenSize, 32)
    fc4: Linear(HiddenSize, 32)
    classifier: Linear(32 * 4, 3)                # 将四个分类器的输出堆叠后送入一个学习型分类器
  forward x, hidden0:
    let
      (output, hiddenN) = gru1(x, hidden0)
      clf1 = hiddenN[0, _, _].squeeze(0).fc1.relu
      clf2 = hiddenN[1, _, _].squeeze(0).fc2.relu
      clf3 = hiddenN[2, _, _].squeeze(0).fc3.relu
      clf4 = hiddenN[3, _, _].squeeze(0).fc4.relu

    # 将所有结果拼接起来
    # 由于目前尚未实现拼接操作的反向传播,我们通过堆叠的方式“作弊”
    # 然后再展平
    result = stack(clf1, clf2, clf3, clf4, axis = 2)
    result = classifier(result.flatten)

# 初始化模型
let
  ctx = newContext Tensor[float32]
  model = ctx.init(TheGreatSequencer)
  optim = model.optimizer(SGD, 0.01'f32)

# ...
let exam = ctx.variable([
    [float32 0.10, 0.20, 0.30], # 递增
    [float32 0.10, 0.90, 0.95], # 递增
    [float32 0.45, 0.50, 0.55], # 递增
    [float32 0.10, 0.30, 0.20], # 非单调
    [float32 0.20, 0.10, 0.30], # 非单调
    [float32 0.98, 0.97, 0.96], # 递减
    [float32 0.12, 0.05, 0.01], # 递减
    [float32 0.95, 0.05, 0.07]  # 非单调
  ])
# ...
echo answer.unsqueeze(1)
# Tensor[ex05_sequence_classification_GRU.SeqKind] of shape [8, 1] of type "SeqKind" on backend "Cpu"
# 	  Increasing|
# 	  Increasing|
# 	  Increasing|
# 	  NonMonotonic|
# 	  NonMonotonic|
# 	  Increasing| <----- 错误!
# 	  Decreasing|
# 	  NonMonotonic|

组合模型

网络模型也可以作为其他网络定义中的层。 上面的手写数字识别模型也可以这样写:

import arraymancer

network SomeConvNet:
  layers h, w:
    cv1:        Conv2D(@[1, h, w], 20, (5, 5))
    mp1:        Maxpool2D(cv1.out_shape, (2,2), (0,0), (2,2))
    cv2:        Conv2D(mp1.out_shape, 50, (5, 5))
    mp2:        MaxPool2D(cv2.out_shape, (2,2), (0,0), (2,2))
    fl:         Flatten(mp2.out_shape)
  forward x:
    x.cv1.relu.mp1.cv2.relu.mp2.fl

# 这个模型可以这样初始化:let model = ctx.init(SomeConvNet, h = 28, w = 28)

# 函数 `out_shape` 和 `in_shape` 返回一个 `seq[int]` 是一种约定(但并非严格必要),
# 适用于具有明确输出和输入尺寸的层或模型。
proc out_shape*[T](self: SomeConvNet[T]): seq[int] =
  self.fl.out_shape
proc in_shape*[T](self: SomeConvNet[T]): seq[int] =
  self.cv1.in_shape

network DemoNet:
  layers:
    # 这里我们将之前定义的 SomeConvNet 用作一层
    cv:         SomeConvNet(28, 28)
    hidden:     Linear(cv.out_shape[0], 500)
    classifier: Linear(hidden.out_shape[0], 10)
  forward x:
    x.cv.hidden.relu.classifier

自定义层

也可以创建完全自定义的层。 相关文档可以在官方 API 文档中找到。

CPU、CUDA 和 OpenCL 上的张量

目前,Tensor、CudaTensor 和 CLTensor 尚未实现完全相同的功能。此外,CudaTensor 和 CLTensor 只能是 float32 或 float64 类型,而 CpuTensor 则可以是整数、字符串、布尔值或任何自定义对象。

以下是核心功能的对比表。

操作 Tensor CudaTensor ClTensor
访问张量属性 [x] [x] [x]
张量创建 [x] 通过转换 CPU 张量 通过转换 CPU 张量
访问或修改单个元素 [x] [] []
遍历张量 [x] [] []
张量切片 [x] [x] [x]
切片赋值 a[1,_] = 10 [x] [] []
比较 == [x] [] []
元素级基本运算 [x] [x] [x]
通用函数 [x] [] []
自动广播操作 [x] [x] [x]
矩阵-矩阵和矩阵-向量乘法 [x] [x] [x]
显示张量 [x] [x] [x]
高阶函数(map、apply、reduce、fold) [x] 仅限内部使用 仅限内部使用
转置 [x] [x] []
转换为连续存储 [x] [x] []
改变形状 [x] [x] []
显式广播 [x] [x] [x]
维度置换 [x] [] []
沿现有维度拼接张量 [x] [] []
压缩单例维度 [x] [x] []
切片 + 压缩 [x] [] []

Arraymancer 的新特性

完整的变更日志可在 changelog.md 中查看。

为什么选择 Arraymancer 的四个理由

Python 社区难以使 NumPy 跟上时代步伐

  • Numba JIT 编译器
  • Dask 延迟并行计算图
  • Cython 用于简化 Python 中的数值计算
  • 由于 GIL 的存在,纯 Python 中无法实现共享内存并行化(OpenMP)
  • 使用“向量化操作”(即避免在 Python 中使用 for 循环)

为什么不使用一种语言,将所有必要的组件整合在一起,构建出兼具 Python 易用性与高效性的科学计算库呢?

OpenMP 直接内置其中。

研究人员的工作流程往往与低效作斗争

在需要大量科学计算的研究领域中,研究人员通常会经历以下工作流程:Mathematica/Matlab/Python/R(原型开发)→ C/C++/Fortran(速度与内存优化)。

为什么不使用一种既像 Python 一样高效,又像 C 语言一样快速的语言呢?只需编写一次代码,便无需花费数月时间在更低层次上重复同样的工作。

几乎无需依赖即可分发

Arraymancer 的模型可以被打包成一个自包含的二进制文件,该文件仅依赖于 BLAS 库,如 OpenBLAS、MKL 或 Apple Accelerate(所有 Mac 和 iOS 设备上均已提供)。

这意味着用户无需安装庞大的库或语言生态系统即可使用 Arraymancer。这也使其天然适用于资源受限的设备,例如手机和 Raspberry Pi。

弥合深度学习研究与生产之间的鸿沟

当前的深度学习框架主要分为两类:

  • 研究类:Theano、TensorFlow、Keras、Torch、PyTorch
  • 生产类:Caffe、Darknet、(TensorFlow)

此外,除非使用 OpenCV,否则 Python 的预处理步骤通常需要自定义实现(例如手机上的文本/语音预处理)。

  • 以可靠的方式管理和部署 Python(2.7、3.5、3.6)及其软件包版本,需要具备 DevOps 技能(virtualenv、Docker等)。
  • Python 数据科学生态系统无法在嵌入式设备(如 Nvidia Tegra 或无人机)以及手机上运行,尤其是预处理相关的依赖项。
  • TensorFlow 本应弥合研究与生产之间的差距,但其语法和易用性令人头疼。对于研究人员而言,仍然需要两次编码:“先用 Keras 做原型,等到需要底层操作时再转到 TensorFlow”。
  • 已部署的模型是静态的,没有任何框架提供添加新观测值或训练样本的接口。如果希望将模型作为具有在线学习能力的 Web 服务使用,该怎么办?

相关 XKCD 漫画,2018 年 4 月 30 日

Python 环境混乱

那么,为什么选择 Arraymancer?

上述种种痛点看似艰巨,然而得益于 Nim 语言,我们得以实现 Arraymancer:

  • 速度媲美 C 语言
  • 通过 Intel MKL/OpenBLAS 甚至 NNPACK 加速计算
  • 支持 CUDA 和 CuDNN,并可通过元编程动态生成自定义 CUDA 内核
  • 几乎无需依赖即可分发(仅需 BLAS 库)
  • 类似 Python 的语法,支持自定义运算符 a * b 进行张量乘法,而非 a.dot(b)(NumPy/TensorFlow)或 a.mm(b)(Torch)
  • 类似 NumPy 的切片操作,如 t[0..4, 2..10|2]
  • 对于 Nim 尚未提供的功能,可以通过 Nim 与 C、C++、Objective-C 或 JavaScript 的绑定将其引入 Nim。Nim 还提供了非官方的 Python↔Nim 绑定。

未来的抱负

既然 apparently 要想成功就得有个愿景,那我就希望 Arraymancer 能成为:

  • 深度学习视频处理的首选工具。比如:vid = load_video("./cats/youtube_cat_video.mkv")
  • 支持 JavaScript、WebAssembly、Apple Metal、ARM 设备、AMD ROCm、OpenCL 等多种平台,你想得到的它都能支持。
  • 成为一款《星际争霸 II》AI 机器人的基础框架。
  • 专门面向加密货币挖矿用的 FPGA,因为它们把 GPU 的价格抬得太高了,让真正搞深度学习的研究者都买不起了。

版本历史

v0.7.02021/07/04
v0.6.12020/11/03
v0.6.02020/01/08
v0.5.22019/07/19
v0.5.12019/07/19
v0.5.02018/12/23
v0.4.02018/05/05
v0.3.02017/12/13
v0.2.02017/09/24
v0.1.02017/07/12

常见问题

相似工具推荐

openclaw

OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你

349.3k|★★★☆☆|昨天
Agent开发框架图像

stable-diffusion-webui

stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。

162.1k|★★★☆☆|昨天
开发框架图像Agent

everything-claude-code

everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上

142.7k|★★☆☆☆|今天
开发框架Agent语言模型

ComfyUI

ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。

107.9k|★★☆☆☆|今天
开发框架图像Agent

markitdown

MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器

93.4k|★★☆☆☆|今天
插件开发框架

LLMs-from-scratch

LLMs-from-scratch 是一个基于 PyTorch 的开源教育项目,旨在引导用户从零开始一步步构建一个类似 ChatGPT 的大型语言模型(LLM)。它不仅是同名技术著作的官方代码库,更提供了一套完整的实践方案,涵盖模型开发、预训练及微调的全过程。 该项目主要解决了大模型领域“黑盒化”的学习痛点。许多开发者虽能调用现成模型,却难以深入理解其内部架构与训练机制。通过亲手编写每一行核心代码,用户能够透彻掌握 Transformer 架构、注意力机制等关键原理,从而真正理解大模型是如何“思考”的。此外,项目还包含了加载大型预训练权重进行微调的代码,帮助用户将理论知识延伸至实际应用。 LLMs-from-scratch 特别适合希望深入底层原理的 AI 开发者、研究人员以及计算机专业的学生。对于不满足于仅使用 API,而是渴望探究模型构建细节的技术人员而言,这是极佳的学习资源。其独特的技术亮点在于“循序渐进”的教学设计:将复杂的系统工程拆解为清晰的步骤,配合详细的图表与示例,让构建一个虽小但功能完备的大模型变得触手可及。无论你是想夯实理论基础,还是为未来研发更大规模的模型做准备

90.1k|★★★☆☆|今天
语言模型图像Agent