Basalt»3.4.0»API 参考»basalt.nativebridge
模块 索引 GitHub

模块 basalt.nativebridge

8 个公开类型 · 3 个包内可见类型

原生桥接专家层:上下文、张量句柄、128 字节指令队列、自动求导入口。

类型概览

类型种类说明
CommandQueueBuilderclass把算子序列编码成 128 字节定长指令,一次 JNI 调用提交。
NativeContextclass持有一个原生张量上下文:存储、计算图、线程池与优化器状态
NativeLibraryclass原生张量运行时的可用性门面
NativeMLPclass参考实现:只用公开张量与队列 API 搭出的多层感知机。
NativeTensorHandleclass一个原生张量的 Java 句柄,持有不透明地址与所属上下文
NativeContext.Guardclass读锁守卫,关闭它只释放读锁,不销毁上下文
NativeMLP.Activationenum隐藏层可选激活函数:RELU、TANH、SIGMOID。
NativeMLP.OutputActivationenum输出层激活:NONE 表示线性输出,另有 SIGMOID、TANH。
final class CommandQueueBuilder implements AutoCloseable

把算子序列编码成 128 字节定长指令,一次 JNI 调用提交。

每条指令固定 128 字节,按本地字节序写入直接 ByteBuffer:偏移 0 为 u8 算子码,偏移 1 为 u8 标志位(当前恒为 0),偏移 8 到 40 依次是 5 个输入句柄地址,偏移 48 是输出句柄地址,偏移 56 起是 16 个 i32 属性槽,偏移 120 为 8 字节保留位。构造时预分配 8 条指令的容量,超出后按倍增扩容并复制已有字节。

算子按元数占用输入槽:一元算子只写 A,二元算子写 A、B,layerNorm 用 A、B、C,batchNorm2d 用满 A 到 E。形状参数不进指针:softmax 的轴、layerNorm 的 epsilon、conv2d 的核/步长/填充都写进属性槽,浮点以 Float.floatToRawIntBits 落位,dropout 的 64 位种子拆成低、高两个 i32。

原生侧按算子码重建 Op,先校验再写输出:输出不得与任一输入同址(原地算子不可微)、不得重复生产、不得覆盖已被消费的张量。批内指令按追加顺序执行,生产者必须排在消费者之前;被拒绝的指令不写输出,但先前指令已生效,队列本身不做回滚。

示例
try (NativeContext context = NativeContext.create(4)) {
    NativeTensorHandle left = context.zeros(2, 3);
    NativeTensorHandle right = context.zeros(3, 4);
    NativeTensorHandle product = context.zeros(2, 4);
    NativeTensorHandle activated = context.zeros(2, 4);
    CommandQueueBuilder queue = new CommandQueueBuilder(context);
    queue.matMul(left, right, product)
            .relu(product, activated)
            .executeAndClear();
    float[] values = activated.data();
}

注意

非线程安全:指令缓冲、计数与扩容都无同步,跨线程共享同一实例需外部加锁。

注意

execute() 不清空队列;对同一批指令再次执行会因输出已被当前计算图生产而失败,需先调用 NativeContext.clearGraph()。

注意

close() 只清空队列,不释放原生资源,本类未实现 AutoCloseable。

注意

原生错误以 BasaltRuntimeException 抛出;execute 的 JFR 事件在 finally 中提交,失败时同样记录。

参见:basalt.nativebridge.NativeContext, basalt.nativebridge.NativeTensorHandle, basalt.nativebridge.NativeMLP

构造器

CommandQueueBuilder(NativeContext context)

绑定上下文并预分配 8 条指令的直接缓冲区。

注意

缓冲区按 ByteOrder.nativeOrder() 创建,与原生 OpCommand 的字节序一致。

注意

构造不分配张量,也不与计算图交互。

参数
  • context (NativeContext) – 指令与张量所属的上下文;入队句柄都必须属于它

抛出
  • BasaltRuntimeException – context 为 null

方法

matMul(NativeTensorHandle left, NativeTensorHandle right, NativeTensorHandle output) → CommandQueueBuilder

追加矩阵乘:left[m,k] × right[k,n] → [m,n]。

注意

算子只写数据不改形状,输出必须已按目标形状分配。

注意

内维不相等或输出形状不符时,原生侧抛 BasaltRuntimeException。

参数
  • left (NativeTensorHandle) – 形状 (m, k) 的 rank-2 张量

  • right (NativeTensorHandle) – 形状 (k, n) 的 rank-2 张量

  • output (NativeTensorHandle) – 预分配的 (m, n) 张量,元素数须为 m*n

返回

this,便于链式追加

add(NativeTensorHandle left, NativeTensorHandle right, NativeTensorHandle output) → CommandQueueBuilder

追加逐元素加法,按广播规则对齐形状。

注意

广播形状由两侧形状逐轴推导,输出形状必须精确等于该结果。

参数
  • left (NativeTensorHandle) – 左操作数,任意秩

  • right (NativeTensorHandle) – 右操作数,形状须可与 left 广播

  • output (NativeTensorHandle) – 形状须等于广播结果,元素数须匹配

返回

this,便于链式追加

sub(NativeTensorHandle left, NativeTensorHandle right, NativeTensorHandle output) → CommandQueueBuilder

追加逐元素减法,计算 left - right。

参数
  • left (NativeTensorHandle) – 被减数,任意秩

  • right (NativeTensorHandle) – 减数,形状须可与 left 广播

  • output (NativeTensorHandle) – 形状须等于广播结果

返回

this,便于链式追加

mul(NativeTensorHandle left, NativeTensorHandle right, NativeTensorHandle output) → CommandQueueBuilder

追加逐元素乘法,按广播规则对齐形状。

参数
  • left (NativeTensorHandle) – 左操作数,任意秩

  • right (NativeTensorHandle) – 右操作数,形状须可与 left 广播

  • output (NativeTensorHandle) – 形状须等于广播结果

返回

this,便于链式追加

relu(NativeTensorHandle input, NativeTensorHandle output) → CommandQueueBuilder

追加 ReLU:负值置零,正负边界取零。

注意

反向时按输入是否大于零决定梯度是否通过。

参数
  • input (NativeTensorHandle) – 任意秩张量

  • output (NativeTensorHandle) – 形状须与 input 相同

返回

this,便于链式追加

sigmoid(NativeTensorHandle input, NativeTensorHandle output) → CommandQueueBuilder

追加 sigmoid:1 / (1 + exp(-x))。

参数
  • input (NativeTensorHandle) – 任意秩张量

  • output (NativeTensorHandle) – 形状须与 input 相同

返回

this,便于链式追加

tanh(NativeTensorHandle input, NativeTensorHandle output) → CommandQueueBuilder

追加双曲正切,输出落在 (-1, 1)。

参数
  • input (NativeTensorHandle) – 任意秩张量

  • output (NativeTensorHandle) – 形状须与 input 相同

返回

this,便于链式追加

gelu(NativeTensorHandle input, NativeTensorHandle output) → CommandQueueBuilder

追加 GELU,采用 tanh 近似式。

注意

近似式为 0.5x(1 + tanh(√(2/π)(x + 0.044715x³))),非精确 erf 形式。

参数
  • input (NativeTensorHandle) – 任意秩张量

  • output (NativeTensorHandle) – 形状须与 input 相同

返回

this,便于链式追加

silu(NativeTensorHandle input, NativeTensorHandle output) → CommandQueueBuilder

追加 SiLU:x * sigmoid(x)。

参数
  • input (NativeTensorHandle) – 任意秩张量

  • output (NativeTensorHandle) – 形状须与 input 相同

返回

this,便于链式追加

mse(NativeTensorHandle prediction, NativeTensorHandle target, NativeTensorHandle output) → CommandQueueBuilder

追加均方误差,输出单元素标量。

注意

按元素平方差求和后除以元素总数,得到均值而非总和。

注意

prediction 与 target 形状不等时原生侧报错。

参数
  • prediction (NativeTensorHandle) – 预测张量

  • target (NativeTensorHandle) – 目标张量,形状须与 prediction 完全一致

  • output (NativeTensorHandle) – 形状 (1) 的单元素张量

返回

this,便于链式追加

softmax(NativeTensorHandle input, NativeTensorHandle output, int dimension) → CommandQueueBuilder

沿最后一维追加 softmax 归一化。

注意

实现只支持最后一维,其他取值在原生侧被拒绝。

注意

先减去该行最大值再取指数,避免上溢。

参数
  • input (NativeTensorHandle) – 任意秩张量

  • output (NativeTensorHandle) – 形状须与 input 相同

  • dimension (int) – 归一化轴长度,须等于 input 的最后一维且大于 0

返回

this,便于链式追加

crossEntropy(NativeTensorHandle logits, NativeTensorHandle targets, NativeTensorHandle output) → CommandQueueBuilder

追加按类别索引计算的平均交叉熵。

注意

内部按 log-sum-exp 计算,不要求先做 softmax。

注意

索引越界或非有限时原生侧报错。

参数
  • logits (NativeTensorHandle) – 形状 (rows, classes) 的未归一化得分

  • targets (NativeTensorHandle) – 长度 rows 的类别索引,以 float 存放,取值 [0, classes)

  • output (NativeTensorHandle) – 形状 (1) 的单元素张量

返回

this,便于链式追加

layerNorm(NativeTensorHandle input, NativeTensorHandle gamma, NativeTensorHandle beta, NativeTensorHandle output, float epsilon) → CommandQueueBuilder

追加最后一维的层归一化。

注意

统计量按最后一维逐行计算,行数由元素总数除以 dim 得到。

参数
  • input (NativeTensorHandle) – 秩至少为 1 的张量,最后一维即归一化维

  • gamma (NativeTensorHandle) – 形状 (dim) 的缩放参数

  • beta (NativeTensorHandle) – 形状 (dim) 的偏移参数

  • output (NativeTensorHandle) – 形状须与 input 相同

  • epsilon (float) – 加到方差上的稳定项,以 float 位写入属性槽 0

返回

this,便于链式追加

batchNorm2d(NativeTensorHandle input, NativeTensorHandle gamma, NativeTensorHandle beta, NativeTensorHandle runningMean, NativeTensorHandle runningVar, NativeTensorHandle output, float epsilon, float momentum, boolean training) → CommandQueueBuilder

追加 NCHW 批归一化,可写回运行统计。

注意

training 以 i32 存入属性槽 2,非零即真。

注意

归一化使用批内有偏方差,运行方差按 spatial - 1 做无偏修正后更新。

注意

runningMean 与 runningVar 按写锁访问,训练模式下是本批唯一的副产物。

参数
  • input (NativeTensorHandle) – 形状 (N, C, H, W) 的输入

  • gamma (NativeTensorHandle) – 形状 (C) 的缩放参数

  • beta (NativeTensorHandle) – 形状 (C) 的偏移参数

  • runningMean (NativeTensorHandle) – 形状 (C) 的运行均值缓冲,训练时被更新

  • runningVar (NativeTensorHandle) – 形状 (C) 的运行方差缓冲,训练时被更新

  • output (NativeTensorHandle) – 形状须与 input 相同

  • epsilon (float) – 数值稳定项,写入属性槽 0

  • momentum (float) – 运行统计更新系数:running = (1 - momentum) * running + momentum * batch

  • training (boolean) – true 时用批内统计并写回缓冲,false 时用运行统计做推理

返回

this,便于链式追加

conv2d(NativeTensorHandle input, NativeTensorHandle weight, NativeTensorHandle output, int kernelHeight, int kernelWidth, int strideHeight, int strideWidth, int paddingHeight, int paddingWidth) → CommandQueueBuilder

追加二维卷积,NCHW 输入、OIHW 权重。

注意

属性槽 0 到 5 依次存放 kernelHeight、kernelWidth、strideHeight、strideWidth、paddingHeight、paddingWidth。

注意

输出宽 ow 用同一公式按宽度计算,除法向下取整。

注意

不支持分组卷积与膨胀;输入通道数须等于权重第二维。

注意

核大于填充后的输入时原生侧报错。

参数
  • input (NativeTensorHandle) – 形状 (N, C_in, H, W) 的输入

  • weight (NativeTensorHandle) – 形状 (C_out, C_in, kernelHeight, kernelWidth) 的权重

  • output (NativeTensorHandle) – 形状 (N, C_out, oh, ow),oh = (H + 2*paddingHeight - kernelHeight) / strideHeight + 1

  • kernelHeight (int) – 卷积核高,须大于 0

  • kernelWidth (int) – 卷积核宽,须大于 0

  • strideHeight (int) – 纵向步长,≤0 时按 1 处理

  • strideWidth (int) – 横向步长,≤0 时按 1 处理

  • paddingHeight (int) – 纵向两侧填充,负值按 0 处理

  • paddingWidth (int) – 横向两侧填充,负值按 0 处理

返回

this,便于链式追加

conv2d(NativeTensorHandle input, NativeTensorHandle weight, NativeTensorHandle output, int kernelHeight, int kernelWidth, int strideHeight, int strideWidth, int paddingHeight, int paddingWidth, int dilationHeight, int dilationWidth, int groups) → CommandQueueBuilder

追加带膨胀与分组参数的二维卷积。

注意

属性槽 0 到 8 依次存放 kernelHeight、kernelWidth、strideHeight、strideWidth、paddingHeight、paddingWidth、dilationHeight、dilationWidth、groups。

注意

9 参数重载等价于 dilationHeight、dilationWidth、groups 都取 1。

注意

有效核按膨胀展开后大于填充后的输入、通道数不能被 groups 整除,或权重第二维不等于 C_in / groups 时,原生侧报错。

注意

输出宽 ow 用同一公式按宽度计算,除法向下取整。

参数
  • input (NativeTensorHandle) – 形状 (N, C_in, H, W) 的输入

  • weight (NativeTensorHandle) – 形状 (C_out, C_in / groups, kernelHeight, kernelWidth) 的权重

  • output (NativeTensorHandle) – 形状 (N, C_out, oh, ow),oh = (H + 2*paddingHeight - eh) / strideHeight + 1,eh = dilationHeight * (kernelHeight - 1) + 1

  • kernelHeight (int) – 卷积核高,须大于 0

  • kernelWidth (int) – 卷积核宽,须大于 0

  • strideHeight (int) – 纵向步长,≤0 时按 1 处理

  • strideWidth (int) – 横向步长,≤0 时按 1 处理

  • paddingHeight (int) – 纵向两侧填充,负值按 0 处理

  • paddingWidth (int) – 横向两侧填充,负值按 0 处理

  • dilationHeight (int) – 纵向膨胀系数,≤0 时按 1 处理

  • dilationWidth (int) – 横向膨胀系数,≤0 时按 1 处理

  • groups (int) – 卷积分组数,≤0 时按 1 处理;输入与输出通道数都须被它整除

返回

this,便于链式追加

抛出
  • BasaltRuntimeException – input、weight 或 output 为 null

  • IllegalArgumentException – 某个句柄属于其他上下文

groupNorm(NativeTensorHandle input, NativeTensorHandle gamma, NativeTensorHandle beta, NativeTensorHandle output, int groups, float epsilon) → CommandQueueBuilder

追加 NCHW 分组归一化。

注意

属性槽 0 为分组数,槽 1 为 epsilon 的 float 位。

注意

每组在连续的 channelsPerGroup 个通道及其全部空间位置上统计均值与有偏方差,再按通道做 gamma、beta 仿射。

注意

输入秩小于 2、C 不能被 groups 整除、gamma 或 beta 长度不等于 C、输出形状与输入不同时,原生侧报错。

参数
  • input (NativeTensorHandle) – 秩至少为 2 的输入,第 0 轴为批、第 1 轴为通道,其后各轴合并为空间维

  • gamma (NativeTensorHandle) – 形状 (C) 的缩放参数

  • beta (NativeTensorHandle) – 形状 (C) 的偏移参数

  • output (NativeTensorHandle) – 形状须与 input 完全相同

  • groups (int) – 分组数,≤0 时按 1 处理;须整除通道数 C

  • epsilon (float) – 加到方差上的稳定项,以 float 位写入属性槽 1

返回

this,便于链式追加

抛出
  • BasaltRuntimeException – input、gamma、beta 或 output 为 null

  • IllegalArgumentException – 某个句柄属于其他上下文

maxPool2d(NativeTensorHandle input, NativeTensorHandle output, int kernelHeight, int kernelWidth, int strideHeight, int strideWidth) → CommandQueueBuilder

追加 NCHW 最大池化,无填充。

注意

属性槽 0 到 3 依次存放 kernelHeight、kernelWidth、strideHeight、strideWidth。

注意

窗大于输入时报错;接口不提供填充参数。

参数
  • input (NativeTensorHandle) – 形状 (N, C, H, W) 的输入

  • output (NativeTensorHandle) – 形状 (N, C, oh, ow),oh = (H - kernelHeight) / strideHeight + 1

  • kernelHeight (int) – 池化窗高,≤0 时按 1 处理

  • kernelWidth (int) – 池化窗宽,≤0 时按 1 处理

  • strideHeight (int) – 纵向步长,≤0 时按 1 处理

  • strideWidth (int) – 横向步长,≤0 时按 1 处理

返回

this,便于链式追加

dropout(NativeTensorHandle input, NativeTensorHandle output, float probability, boolean training, long seed) → CommandQueueBuilder

追加 inverted dropout,训练时按 1/(1-p) 缩放。

注意

掩码逐元素由 xorshift 生成,相同 seed 与长度得到相同掩码。

注意

probability 不在 [0, 1) 时原生侧报错。

注意

反向复用同一 seed 重建掩码,因此前向与反向必须传相同参数。

参数
  • input (NativeTensorHandle) – 任意秩张量

  • output (NativeTensorHandle) – 形状须与 input 相同

  • probability (float) – 丢弃概率,取值 [0, 1),0 表示原样输出

  • training (boolean) – false 时直接复制输入,不生成掩码

  • seed (long) – 掩码随机种子,低 32 位与高 32 位分别写入属性槽 2、3

返回

this,便于链式追加

embedding(NativeTensorHandle indices, NativeTensorHandle weight, NativeTensorHandle output) → CommandQueueBuilder

追加按索引查表,输出在索引形状后追加词向量维。

注意

索引按 float 截断取整,越界或非有限时报错。

注意

反向时把梯度累加到被选中的行,其余行梯度为零。

参数
  • indices (NativeTensorHandle) – 整数索引以 float 存放,元素个数即查表行数,取值 [0, vocab)

  • weight (NativeTensorHandle) – 形状 (vocab, dim) 的嵌入矩阵

  • output (NativeTensorHandle) – indices 形状后接 dim,元素数须为 rows * dim

返回

this,便于链式追加

batchedMatMul(NativeTensorHandle left, NativeTensorHandle right, NativeTensorHandle output) → CommandQueueBuilder

追加批量矩阵乘,左右均为 rank-3。

注意

要求两边的批大小与内维分别相等。

参数
  • left (NativeTensorHandle) – 形状 (B, M, K) 的左操作数

  • right (NativeTensorHandle) – 形状 (B, K, N) 的右操作数

  • output (NativeTensorHandle) – 形状 (B, M, N)

返回

this,便于链式追加

permute(NativeTensorHandle input, NativeTensorHandle output, int... permutation) → CommandQueueBuilder

追加轴重排,最多支持 4 维。

注意

属性槽 0 存轴数,槽 1 起依次存各轴下标。

注意

原生侧还要求长度等于输入秩、下标小于秩且互不重复。

参数
  • input (NativeTensorHandle) – 秩等于 permutation 长度的张量

  • output (NativeTensorHandle) – 形状为 input 各轴按 permutation 重排后的结果

  • permutation (int...) – 输出第 i 轴取自输入的哪一轴,长度 1 到 4

返回

this,便于链式追加

抛出
  • IllegalArgumentException – permutation 长度不在 [1, 4]

reshape(NativeTensorHandle input, NativeTensorHandle output, int... shape) → CommandQueueBuilder

追加形状变换,元素顺序保持不变。

注意

属性槽 0 存维数,槽 1 起依次存各维长度。

注意

维度非正或元素总数不匹配时原生侧报错。

参数
  • input (NativeTensorHandle) – 任意秩张量

  • output (NativeTensorHandle) – 形状为 shape,元素总数须与 input 相同

  • shape (int...) – 目标形状,1 到 4 个正维度

返回

this,便于链式追加

抛出
  • IllegalArgumentException – shape 长度不在 [1, 4]

size() → int

返回已追加且尚未清空的指令条数。

返回

指令条数,清空后为 0

capacity() → int

返回缓冲区当前可容纳的指令条数。

注意

扩容时容量翻倍并复制已有指令;该值不是字节数。

返回

以指令条数计的容量,初始为 8

execute()

以上下文默认线程数执行整批指令,不清空队列。

注意

队列为空时直接返回,不进入原生层,也不产生事件。

注意

执行后计算图新增对应节点,再次执行同一批指令前必须先 clearGraph。

execute(int threads)

以指定线程数执行整批指令,不清空队列。

注意

校验先于空队列判断,threads 越界时即使队列为空也会抛出。

注意

线程数只影响内核的并行调度,不改变指令语义与结果。

参数
  • threads (int) – 并行度,取值 [0, 256];0 与 1 都落到单线程池,2 到 256 按该数量复用线程池

抛出
  • IllegalArgumentException – threads 小于 0 或大于 256

executeAndClear()

执行后立即清空队列,供逐批训练循环复用。

注意

等价于先 execute() 再 clear(),执行失败时不会清空。

clear()

丢弃全部指令,保留已分配的缓冲区容量。

注意

只重置计数与缓冲位置,不影响已写入的张量与计算图。

close()

清空队列;不释放原生资源。

注意

本类未实现 AutoCloseable,close 与 clear 等价。

toString() → String

返回指令条数与容量组成的描述文本。

返回

形如 CommandQueueBuilder[commands=2, capacity=8] 的字符串

字段

OP_MATMUL()static

OP_MATMUL = 1:rank-2 矩阵乘算子码。

读取输入 A、B 与输出,不带属性;要求两侧秩均为 2 且内维相等。

OP_ADD()static

OP_ADD = 2:逐元素加法,按广播对齐。

OP_RELU()static

OP_RELU = 3:逐元素 ReLU。

OP_SUB()static

OP_SUB = 4:逐元素减法,按广播对齐。

OP_MUL()static

OP_MUL = 5:逐元素乘法,按广播对齐。

OP_SIGMOID()static

OP_SIGMOID = 6:逐元素 sigmoid。

OP_TANH()static

OP_TANH = 7:逐元素 tanh。

OP_MSE()static

OP_MSE = 8:均方误差,输出单元素标量。

OP_SOFTMAX()static

OP_SOFTMAX = 9:沿最后一维归一化。

属性槽 0 存放归一化轴的长度,须与输入最后一维一致。

OP_CROSS_ENTROPY()static

OP_CROSS_ENTROPY = 10:按类别索引的交叉熵。

OP_GELU()static

OP_GELU = 11:tanh 近似的 GELU。

OP_SILU()static

OP_SILU = 12:SiLU(swish)。

OP_LAYER_NORM()static

OP_LAYER_NORM = 13:最后一维层归一化。

读取输入 A、gamma B、beta C 与输出,属性槽 0 以 float 位存放 epsilon。

OP_BATCH_NORM()static

OP_BATCH_NORM = 14:NCHW 批归一化。

读取输入 A、gamma B、beta C、运行均值 D、运行方差 E 与输出;属性槽 0、1 为 epsilon 与 momentum,槽 2 为训练标志。

OP_CONV2D()static

OP_CONV2D = 15:NCHW 输入、OIHW 权重的卷积。

属性槽 0 到 5 依次存放核高、核宽、纵向步长、横向步长、纵向填充、横向填充。

OP_MAX_POOL2D()static

OP_MAX_POOL2D = 16:NCHW 最大池化。

属性槽 0 到 3 依次存放核高、核宽、纵向步长、横向步长。

OP_DROPOUT()static

OP_DROPOUT = 17:inverted dropout。

属性槽 0 为丢弃概率的 float 位,槽 1 为训练标志,槽 2、3 为种子的低、高 32 位。

OP_EMBEDDING()static

OP_EMBEDDING = 18:按索引查表。

OP_BATCHED_MATMUL()static

OP_BATCHED_MATMUL = 19:rank-3 批量矩阵乘。

OP_PERMUTE()static

OP_PERMUTE = 20:重排轴顺序。

属性槽 0 为轴数,槽 1 起依次存放各输出轴对应的输入轴下标。

OP_RESHAPE()static

OP_RESHAPE = 21:改变形状,不改变元素顺序。

属性槽 0 为维数,槽 1 起依次存放各维长度。

OP_GROUP_NORM()static

OP_GROUP_NORM = 22:NCHW 分组归一化。

读取输入 A、gamma B、beta C 与输出;属性槽 0 为分组数,槽 1 以 float 位存放 epsilon。

COMMAND_BYTES()static

COMMAND_BYTES = 128:单条指令的字节数。

原生侧按此长度逐条解析缓冲区,因此缓冲区容量必须是它的整数倍。

final class NativeContext implements AutoCloseable

持有一个原生张量上下文:存储、计算图、线程池与优化器状态

上下文是原生状态的唯一所有者:张量存储(slotmap 加地址索引)、自微分计算图、按线程数缓存的 rayon 线程池,以及按张量地址保存的 Adam 一阶与二阶矩,都挂在同一个 Context 上。

生命周期由 ReentrantReadWriteLock 保护。每个 JNI 调用都在 guard() 取得的读锁内执行,close() 取写锁并把指针原子置零,因此销毁最多发生一次,并且会等待在途调用结束。

句柄持有上下文的强引用,上下文不会先于其张量被回收。关闭后 guard() 抛 IllegalStateException,句柄的后续操作在取锁阶段即失败,不会解引用已释放内存。

示例
try (NativeContext ctx = NativeContext.create(4)) {
    NativeTensorHandle weight = ctx.parameter(4, 3);
    weight.randomize(42L, 0.1f);
    try (NativeTensorHandle batch = ctx.of(new float[]{1f, 2f, 3f}, 1, 3)) {
        long[] stats = ctx.stats();
        System.out.println(stats[0] + " tensors, graph nodes " + ctx.graphSize());
        System.out.println(batch.rank() + " dims, weight norm " + weight.norm());
    }
}

注意

线程安全:多个线程可并发调用,读锁允许多个 JNI 调用并行,close() 需等待在途调用退出。

注意

生命周期:close() 幂等;未显式关闭时由 Cleaner 在对象不可达后兜底销毁。

注意

失败模式:引擎不可用时构造抛 basalt.BasaltRuntimeException;关闭后调用抛 IllegalStateException。

参见:basalt.nativebridge.NativeTensorHandle, basalt.nativebridge.NativeLibrary, basalt.nativebridge.NativeContext.Guard

方法

create() → NativeContextstatic

创建使用全部可用处理器的上下文

等价于 create(0):线程数 0 交给 Rust 侧按 available_parallelism 决定,实际线程池在首次执行指令队列或反向传播时才建立。

返回

持有独立原生上下文的新实例

create(int threads) → NativeContextstatic

创建指定原生线程数提示的上下文

注意

线程数只作为提示保存,线程池按该值缓存在上下文内,相同取值复用同一个池。

参数
  • threads (int) – 原生线程数提示;0 表示由 Rust 侧选择,合法区间为 [0, 256]

返回

持有独立原生上下文的新实例

抛出
  • IllegalArgumentException – threads 小于 0 或大于 256

  • basalt.BasaltRuntimeException – 原生引擎不可用,消息含加载错误与预期路径

  • IllegalStateException – 原生上下文分配返回空指针

threads() → int

返回构造时记录的线程数提示

返回

线程数提示;0 表示自动

isOpen() → boolean

判断上下文是否仍持有有效原生指针

返回

指针非零时为 true

guard() → Guard

获取读锁并返回携带原生指针的 Guard

先取得读锁再读取指针,因此 close() 不可能在 Guard 存活期间完成销毁。读锁与指针校验都成功后返回 Guard,调用方必须在 JNI 调用结束后关闭它。

注意

Guard 关闭时只释放读锁,不销毁上下文。

返回

持有读锁的 Guard,需在 JNI 调用后关闭

抛出
  • IllegalStateException – 上下文已关闭,指针为零

zeros(int... shape) → NativeTensorHandle

创建零初始化的推理张量,不需要梯度

注意

元素总数按 Math.multiplyExact 计算,超过 int 范围即拒绝,因为 Java 侧视图是 float 数组。

参数
  • shape (int...) – 各维长度,必须至少一维且全部为正

返回

requiresGrad 为 false 的零张量句柄

抛出
  • basalt.BasaltRuntimeException – shape 为 null

  • IllegalArgumentException – shape 为空、含非正维度、元素总数溢出或超过 Integer.MAX_VALUE

parameter(int... shape) → NativeTensorHandle

创建零初始化的可训练张量,requiresGrad 为真

注意

初始值为零,通常随后调用 randomize 或 setData 赋初值。

参数
  • shape (int...) – 各维长度,必须至少一维且全部为正

返回

requiresGrad 为 true 的零张量句柄

抛出
  • basalt.BasaltRuntimeException – shape 为 null

  • IllegalArgumentException – shape 为空、含非正维度、元素总数溢出或超过 Integer.MAX_VALUE

of(float[] data, int... shape) → NativeTensorHandle

用给定数据创建不需要梯度的张量

注意

数据在构造时被复制进原生缓冲区,之后修改 Java 数组不影响张量。

参数
  • data (float[]) – 按行主序排列的元素,长度必须等于 shape 的元素总数

  • shape (int...) – 各维长度,必须至少一维且全部为正

返回

requiresGrad 为 false 的张量句柄

抛出
  • basalt.BasaltRuntimeException – data 或 shape 为 null,或数据含非有限值

  • IllegalArgumentException – 数据长度与 shape 不符,或 shape 本身非法

of(float[] data, boolean requiresGrad, int... shape) → NativeTensorHandle

用给定数据创建张量并可指定是否需要梯度

参数
  • data (float[]) – 按行主序排列的元素,长度必须等于 shape 的元素总数

  • requiresGrad (boolean) – 是否参与梯度计算

  • shape (int...) – 各维长度,必须至少一维且全部为正

返回

绑定到当前上下文的张量句柄

抛出
  • basalt.BasaltRuntimeException – data 或 shape 为 null,或数据含非有限值

  • IllegalArgumentException – 数据长度与 shape 不符,或 shape 本身非法

random(int[] shape, long seed, float scale, boolean requiresGrad) → NativeTensorHandle

创建张量并用 seed 与 scale 填充随机值

注意

先按 shape 分配零张量再填充;填充失败时会关闭已分配的句柄再抛出原异常,不泄漏原生内存。

参数
  • shape (int[]) – 各维长度,必须至少一维且全部为正

  • seed (long) – 伪随机种子,相同取值可复现

  • scale (float) – 幅度,必须有限且非负

  • requiresGrad (boolean) – 是否参与梯度计算

返回

已填充随机数据的张量句柄

抛出
  • basalt.BasaltRuntimeException – shape 为 null、scale 为负或非有限

  • IllegalArgumentException – shape 非法或元素总数超出 int 范围

backward(NativeTensorHandle root)

从 root 反向传播,梯度累加到各张量

注意

梯度是累加的,重复调用前应先对参数调用 zeroGrad。

参数
  • root (NativeTensorHandle) – 计算图输出张量,必须属于当前上下文

抛出
  • basalt.BasaltRuntimeException – root 为 null,或 root 已关闭

  • IllegalArgumentException – root 属于其他上下文

clipGradNorm(java.util.List<NativeTensorHandle> tensors, float maxNorm) → double

按全局 L2 范数裁剪梯度,返回裁剪前范数

注意

范数不超过阈值时不修改任何梯度,但仍返回实际范数。

参数
  • tensors (java.util.List<NativeTensorHandle>) – 参数张量列表,每一项都必须属于当前上下文

  • maxNorm (float) – 裁剪阈值,必须有限且非负

返回

裁剪前的全局梯度范数;空列表时为 0.0

抛出
  • IllegalArgumentException – 某个张量属于其他上下文

  • basalt.BasaltRuntimeException – maxNorm 为负或非有限,或某个张量已关闭

clearGraph()

清空计算图,张量数据保持不变

清空后不能再对旧节点执行反向传播,新的指令队列执行会重新建图。张量本身与其梯度缓冲不受影响。

抛出
  • IllegalStateException – 上下文已关闭

graphSize() → int

返回计算图节点数量

返回

当前图中的节点数

抛出
  • IllegalStateException – 上下文已关闭

stats() → long[]

返回存活张量数、存活字节数与图节点数

注意

字节数按数据与梯度缓冲的实际容量统计,可用于诊断内存占用。

返回

长度 3 的数组:存活张量数、存活字节数、图节点数

抛出
  • IllegalStateException – 上下文已关闭

close()

销毁原生上下文,重复调用无效果

取写锁后以 getAndSet(0) 取出指针,非零时调用原生销毁,再执行 Cleaner 注册的清理动作;写锁保证在途读锁调用全部退出后才真正释放,指针置零保证只销毁一次。

注意

幂等:第二次调用取出的是 0,不会重复销毁。

注意

关闭后该上下文创建的所有句柄失效,其 close() 变为无操作。

toString() → String

返回开放状态与线程数的摘要

返回

形如 NativeContext[open=true, threads=4] 的字符串

final class NativeLibrary

原生张量运行时的可用性门面

动态库只由 basalt.core.NativeKernels 在类初始化时加载一次,本类仅转发可用性、错误信息与路径查询,并额外提供 version() 与 requireAvailable()。单一加载点避免经典内核与张量引擎同时使用时出现已在其他类加载器中加载的失败。

查找顺序固定为三步:先按系统属性 basalt.native.path 定位文件,存在就 System.load;否则从 classpath 的 /native/平台标签/ 解压到临时目录加载;最后回退到 System.loadLibrary,由 java.library.path 解析。

available() 表示三步中任一步成功。失败时 loadError() 保留首次捕获的异常摘要,libraryPath() 报告实际加载位置或预期位置,requireAvailable() 用两者拼出可直接采取行动的错误消息。

注意

basalt.native.path 的默认值是 build/native 下的平台库文件名,未设置属性时即按该路径查找。

注意

默认文件名按平台选择:Windows 为 basalt_native.dll,macOS 为 libbasalt_native.dylib,其余为 libbasalt_native.so;classpath 资源中的平台标签形如 windows-x86_64。

注意

加载在类初始化阶段完成,结果不可变,运行期不会重试。

注意

加载失败不影响纯 Java 路径,经典估计器会自动回退。

注意

requireAvailable() 抛 basalt.BasaltRuntimeException,它是 IllegalStateException 的子类。

参见:basalt.nativebridge.NativeContext, basalt.core.NativeKernels

方法

available() → booleanstatic

原生引擎是否加载成功

返回

true 表示三步查找中任一步成功

loadError() → Stringstatic

返回加载失败摘要

返回

异常类名与消息;加载成功时为空字符串

libraryPath() → Stringstatic

返回实际或预期的库文件绝对路径

返回

加载成功时为实际文件路径,失败时为默认预期路径的绝对形式

version() → intstatic

返回引擎 ABI 版本,不可用时为 0

返回

原生版本号;库不可用时为 0

requireAvailable()static

引擎不可用时抛出带诊断信息的异常

错误消息由三段拼成:固定前缀、loadError() 的内容,以及 libraryPath() 给出的预期路径与运行 native-build.sh 的提示,便于直接定位是未编译还是路径不对。

抛出
  • basalt.BasaltRuntimeException – 原生库不可用;消息包含加载错误与预期路径

final class NativeMLP implements AutoCloseable

参考实现:只用公开张量与队列 API 搭出的多层感知机。

构造时按 layerSizes 逐层建立权重与偏置:权重形状 (layerSizes[i], layerSizes[i+1]),用 Xavier 均匀分布初始化,缩放系数 sqrt(6 / (fanIn + fanOut)),种子为 seed + 1009 * (i + 1);偏置为同宽的全零可训练张量。层数等于 layerSizes 长度减一。

fit 的每个 mini-batch 依次执行:前向(matMul → add → 激活)→ mse → 执行队列 → 读取损失 → backward → 逐参数 adam → zeroGrad → clearGraph。Adam 固定 beta1=0.9、beta2=0.999、epsilon=1e-8,步数从 1 开始全局递增,weightDecay 以解耦方式加到更新量上。

批次按打乱后的索引顺序填充;末批不足 batchSize 时从 epoch 头部回绕取样本,使原生张量形状保持不变,代价是末批存在少量重复样本。

示例
try (NativeContext context = NativeContext.create(4)) {
    NativeMLP mlp = new NativeMLP(context, new int[]{2, 16, 1},
            NativeMLP.Activation.RELU, NativeMLP.OutputActivation.NONE, 42L);
    float[][] features = {{0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}};
    float[][] targets = {{0.0f}, {1.0f}, {1.0f}, {0.0f}};
    float loss = mlp.fit(features, targets, 200, 4, 0.05f, 0.0f);
    float[] predictions = mlp.predictScalar(features);
    mlp.close();
}

注意

所有张量归构造时传入的 NativeContext 所有;参数在构造时一次性分配,训练不改变形状。

注意

训练中出现非有限损失立即抛 IllegalStateException,不继续迭代。

注意

fit 与 predict 结束都会清空计算图并释放临时张量,返回的 float[] 是副本。

注意

close() 只释放本实例的参数张量与队列,不关闭上下文;关闭后 fit 与 predict 抛 IllegalStateException。

参见:basalt.nativebridge.CommandQueueBuilder, basalt.nativebridge.NativeContext, basalt.nativebridge.NativeTensorHandle

构造器

NativeMLP(NativeContext context, int[] layerSizes, Activation activation, OutputActivation outputActivation, long seed)

按层宽建网,初始化 Xavier 权重与零偏置。

注意

layerSizes 在构造时被复制,之后修改入参数组不影响实例。

注意

构造只分配参数与队列,批次张量在 fit 与 predict 时按实际批宽分配。

参数
  • context (NativeContext) – 张量与计算图所属的上下文

  • layerSizes (int[]) – 从输入到输出的各层宽度,至少两个元素且全部为正

  • activation (Activation) – 隐藏层激活函数

  • outputActivation (OutputActivation) – 输出层激活函数,NONE 表示线性输出

  • seed (long) – 权重初始化与批次打乱的种子

抛出
  • IllegalArgumentException – layerSizes 少于两个元素或含非正宽度

  • BasaltRuntimeException – context、layerSizes、activation 或 outputActivation 为 null

方法

layerSizes() → int[]

返回层宽数组的副本。

返回

与构造参数内容相同的新数组

parameters() → List<NativeTensorHandle>

按层顺序返回权重与偏置,权重在前。

返回

只读列表,元素交替为 weight(0)、bias(0)、weight(1)、bias(1)……

weight(int layer) → NativeTensorHandle

返回指定层的权重张量。

注意

索引越界由底层列表抛出 IndexOutOfBoundsException,源码未做显式校验。

参数
  • layer (int) – 层索引,从 0 开始,最大为层数减一

返回

形状 (layerSizes[layer], layerSizes[layer+1]) 的可训练张量

bias(int layer) → NativeTensorHandle

返回指定层的偏置张量。

参数
  • layer (int) – 层索引,从 0 开始,最大为层数减一

返回

形状 (layerSizes[layer+1]) 的可训练张量,初值为全零

fit(float[][] features, float[][] targets, int epochs, int batchSize, float learningRate, float weightDecay) → float

用 Adam 训练,返回最后一个 epoch 的平均 MSE。

注意

每个 batch 结束即更新参数并清零梯度,不累积跨批梯度。

注意

步数 step 在 backward 之后、adam 之前自增,并作为 Adam 偏差修正的输入。

注意

临时张量在方法返回前关闭,计算图在入口与 finally 中各清空一次。

参数
  • features (float[][]) – 行优先特征矩阵,列数须等于 layerSizes[0]

  • targets (float[][]) – 目标矩阵,行数与 features 相同,列数须等于最后一层宽度

  • epochs (int) – 完整遍历数据的轮数,须为正

  • batchSize (int) – 每批行数,须为正;超过样本数时按样本数截断

  • learningRate (float) – Adam 学习率

  • weightDecay (float) – 解耦权重衰减系数,0 表示不衰减

返回

最后一个 epoch 各批 MSE 的算术平均

抛出
  • IllegalArgumentException – 数据集为空、行数不等、行列宽不符,或 epochs、batchSize 非正

  • IllegalStateException – 实例已关闭,或某步损失为非有限值

  • BasaltRuntimeException – features 或 targets 为 null

predict(float[][] features) → float[]

批量前向,返回行优先的展平预测结果。

注意

整批一次前向,批宽等于样本数;空输入直接返回零长度数组。

注意

不修改参数、梯度与优化器状态。

参数
  • features (float[][]) – 行优先特征矩阵,每行列数须等于 layerSizes[0]

返回

长度 rows * outputSize 的数组,按行拼接

抛出
  • IllegalArgumentException – 任一行宽不等于输入宽度

  • IllegalStateException – 实例已关闭

predictScalar(float[][] features) → float[]

单输出模型的预测包装,每行返回一个值。

注意

输出宽度校验在委托 predict 之前完成,因此宽输出模型会先报错。

参数
  • features (float[][]) – 行优先特征矩阵

返回

长度等于样本数的数组

抛出
  • IllegalStateException – 最后一层宽度不为 1

gradientNorm() → double

返回所有参数梯度的全局 L2 范数。

注意

在 zeroGrad 之后调用得到 0;fit 内部每步更新后即清零。

返回

各参数梯度范数平方和的开方

close()

释放参数张量并清空队列,可重复调用。

注意

不关闭 NativeContext;重复调用无副作用。

toString() → String

返回层宽、隐藏激活与输出激活的描述。

返回

形如 NativeMLP[2, 16, 1][activation=RELU, output=NONE] 的字符串

final class NativeTensorHandle implements AutoCloseable

一个原生张量的 Java 句柄,持有不透明地址与所属上下文

对象只保存一个不透明 long 与 shape 副本。数据是 Rust 侧的连续 f32 缓冲区,梯度缓冲惰性分配,Java 数组不会被 pin;除非显式调用 data() 或 grad(),否则没有批量数据穿越 JNI 边界。

句柄持有 NativeContext 的强引用,因此上下文不会先于张量被回收。每个操作都先经 context.guard() 取得读锁再调用原生方法,上下文一旦关闭,取锁阶段就抛异常,句柄随之失效。

释放幂等且只发生一次:close() 触发 Cleaner 注册的清理动作,State 以 getAndSet(0) 取走地址并交给上下文释放;原生侧对未知地址返回未找到,即使重复释放也不会二次 free。

示例
try (NativeContext ctx = NativeContext.create();
     NativeTensorHandle weight = ctx.parameter(3, 2)) {
    weight.randomize(7L, 0.5f);
    weight.fill(0.1f);
    float[] flat = weight.data();
    System.out.println(weight + " -> " + flat.length);
}

注意

元数据访问器(context、shape、rank、size、requiresGrad)读取 Java 侧字段,关闭后仍可用。

注意

跨上下文传参会抛 IllegalArgumentException,例如把句柄交给另一个上下文的 backward 或 clipGradNorm。

注意

未显式关闭时由 Cleaner 在对象不可达后释放;若上下文已先销毁,则统一回收,句柄释放变为无操作。

参见:basalt.nativebridge.NativeContext, basalt.nativebridge.NativeContext.Guard, basalt.nativebridge.CommandQueueBuilder

方法

context() → NativeContext

返回所属上下文

返回

构造时绑定的上下文引用

shape() → int[]

返回 shape 的副本

返回

新数组,修改它不影响句柄

rank() → int

返回张量维数

返回

shape 的长度

size() → long

返回元素总数

返回

各维长度按 long 累乘的结果

requiresGrad() → boolean

是否参与梯度计算

返回

创建时指定的标志

data() → float[]

把张量数据复制到新数组

注意

每次调用都产生一次完整拷贝,热路径上应避免在循环内反复调用。

返回

长度为 size() 的新 float 数组

抛出
  • IllegalStateException – 句柄已关闭,或所属上下文已关闭

grad() → float[]

复制梯度,未参与反向传播时全为零

注意

原生侧在梯度缓冲为空时按数据长度写零,调用方总能拿到等长数组。

返回

长度为 size() 的新 float 数组

抛出
  • IllegalStateException – 句柄已关闭,或所属上下文已关闭

setData(float[] values)

用新数组覆盖张量数据

参数
  • values (float[]) – 新数据,长度必须等于 size()

抛出
  • basalt.BasaltRuntimeException – values 为 null,或含非有限值

  • IllegalArgumentException – 长度与张量元素总数不符

  • IllegalStateException – 句柄或上下文已关闭

fill(float value)

用同一数值填充全部元素

参数
  • value (float) – 填充值,必须为有限数

抛出
  • basalt.BasaltRuntimeException – value 非有限

  • IllegalStateException – 句柄或上下文已关闭

randomize(long seed, float scale)

用伪随机数原地填充张量

注意

使用 xorshift 生成 [0, 1) 上的均匀值,再映射到 [-scale, scale);同参数结果可复现。

参数
  • seed (long) – 伪随机种子,原生侧与 1 取或后作为初始状态

  • scale (float) – 幅度,必须有限且非负

抛出
  • basalt.BasaltRuntimeException – scale 为负或非有限

  • IllegalStateException – 句柄或上下文已关闭

zeroGrad()

把梯度缓冲清零

注意

梯度尚未分配时不做任何事,不会为清零而分配缓冲。

抛出
  • IllegalStateException – 句柄或上下文已关闭

sgd(float learningRate)

以零权重衰减执行一步 SGD

注意

等价于 sgd(learningRate, 0.0f)。

参数
  • learningRate (float) – 学习率,必须有限且非负

抛出
  • basalt.BasaltRuntimeException – learningRate 为负或非有限

  • IllegalStateException – 句柄或上下文已关闭

sgd(float learningRate, float weightDecay)

执行一步带动量衰减的 SGD

注意

更新前确保梯度缓冲已分配,梯度为空时按零梯度处理。

参数
  • learningRate (float) – 学习率,必须有限且非负

  • weightDecay (float) – 权重衰减系数

抛出
  • basalt.BasaltRuntimeException – learningRate 为负或非有限

  • IllegalStateException – 句柄或上下文已关闭

adam(float learningRate, float beta1, float beta2, float epsilon, float weightDecay, long step)

执行一步 Adam 更新

注意

一阶与二阶矩按张量地址保存在所属上下文内,首次使用时按数据长度分配,长度变化时重置为零。

参数
  • learningRate (float) – 学习率,必须有限且非负

  • beta1 (float) – 一阶矩衰减,必须落在 [0, 1)

  • beta2 (float) – 二阶矩衰减,必须落在 [0, 1)

  • epsilon (float) – 数值稳定项,必须为正

  • weightDecay (float) – 权重衰减系数

  • step (long) – 步数,必须为正,用于偏差校正

抛出
  • basalt.BasaltRuntimeException – 学习率非法、beta 越界、epsilon 非正或 step 非正

  • IllegalStateException – 句柄或上下文已关闭

norm() → double

返回数据的 L2 范数

返回

平方和以 double 累加后开方

抛出
  • IllegalStateException – 句柄或上下文已关闭

gradNorm() → double

返回梯度的 L2 范数

返回

梯度平方和开方;梯度未分配时为 0.0

抛出
  • IllegalStateException – 句柄或上下文已关闭

isFinite() → boolean

判断数据是否全部为有限值

注意

只检查数据,不检查梯度缓冲。

返回

所有元素均有限时为 true

抛出
  • IllegalStateException – 句柄或上下文已关闭

close()

释放原生张量,重复调用无效果

触发 Cleaner 注册的清理动作:State 以 getAndSet(0) 取走地址,非零时请求所属上下文释放。上下文已关闭时释放被跳过,因为销毁过程已回收全部张量。

注意

幂等:清理动作由同一个 Cleanable 承载,close() 与 Cleaner 合计只执行一次。

toString() → String

返回 shape、梯度标志与地址的摘要

返回

形如 NativeTensor[3, 2][requiresGrad=true, live=...] 的字符串

static final class NativeContext.Guard implements AutoCloseable

读锁守卫,关闭它只释放读锁,不销毁上下文

guard() 在成功取得读锁并确认指针非零后返回 Guard。Guard 保存指针副本,handle() 在 Guard 关闭后抛异常,close() 只释放一次读锁,因此 try-with-resources 是唯一安全用法。

注意

读锁来自 ReentrantReadWriteLock,Guard 必须在获取它的线程上关闭。

注意

Guard 存活期间 close() 会阻塞在写锁上,长耗时操作应尽量缩短持锁区间。

参见:basalt.nativebridge.NativeContext

方法

handle() → long

返回原生上下文指针,Guard 关闭后抛异常

返回

获取 Guard 时读取到的非零指针

抛出
  • IllegalStateException – Guard 已关闭

close()

释放读锁,重复调用无效果

首次调用置位内部标志并解锁一次,之后的调用直接返回;即使被调用两次也不会多释放锁,避免破坏读锁计数。

enum NativeMLP.Activation

隐藏层可选激活函数:RELU、TANH、SIGMOID。

每个隐藏层在 matMul 与加偏置之后按该枚举选择算子,分别对应指令队列的 relu、tanh、sigmoid。

注意

枚举无属性字段,选择只决定前向图写入哪种节点。

注意

该枚举不作用于输出层,输出层由 OutputActivation 控制。

枚举成员

RELU()

max(0, x)

TANH()

双曲正切

SIGMOID()

1 / (1 + e^(−x))

enum NativeMLP.OutputActivation

输出层激活:NONE 表示线性输出,另有 SIGMOID、TANH。

NONE 时最后一层直接输出加偏置后的线性结果,适用于回归;SIGMOID 与 TANH 把输出分别压到 (0, 1) 与 (-1, 1)。

注意

只作用于最后一层,隐藏层仍使用 Activation。

注意

选择 NONE 时最后一层不再写入激活指令,输出张量就是加偏置的结果。

枚举成员

NONE()

输出层不做激活,直接返回 logits

SIGMOID()

输出层接 sigmoid,配合二分类交叉熵

TANH()

输出层接 tanh,输出落在 (−1, 1)

包内可见类型

以下类型没有 public 修饰符,但出现在公开签名中,因此一并列出。它们不是稳定 API,跨版本可能变化。

final class NativeBindings

包内可见的原始 JNI 方法声明表

所有方法均为 native 声明,与 Rust 侧导出的符号一一对应;返回 int 的方法以 0 表示成功,返回 long 的创建方法以 0 表示分配失败,返回 int[] 的方法用于读取形状。

调用方不直接接触这张表:NativeContext 与 NativeTensorHandle 在 Guard 持有的读锁下转发调用,并在返回后补上生命周期与参数校验。

注意

Rust 侧在返回负状态前会先抛 IllegalStateException,因此 Java 调用方不会在操作被拒绝后继续执行。

private static final class NativeContext.State implements Runnable

上下文指针的清理动作,由 Cleaner 执行

NativeContext 构造时把 State 注册到静态 Cleaner,close() 也会调用 cleanable.clean();两条路径都进入 run,先以 getAndSet(0) 取走指针,得到 0 即说明已被另一方释放,直接返回。

抢占到指针的一方调用 NativeBindings.destroyContext;异常被捕获并忽略,因为清理线程不应向外抛出,且上下文注册表使重复销毁成为无操作。

方法

run()

释放上下文指针,至多执行一次

由 Cleaner 线程在上下文不可达时调用,或由 NativeContext.close 通过 cleanable.clean() 同步调用。抢占到非零指针的一方执行 NativeBindings.destroyContext,另一方取到 0 后立即返回。

返回

无返回值;内部异常被吞掉以保证清理线程安全

private static final class NativeTensorHandle.State implements Runnable

张量句柄的释放动作,保证只归还一次

NativeTensorHandle 构造时把 State 注册到静态 Cleaner,close() 与不可达回收都落到 run;指针先被 getAndSet(0),因此重复关闭不会二次释放。

释放委托给 context.releaseTensorQuietly:上下文仍打开时经 Guard 转发到 NativeBindings.releaseTensor,上下文已关闭时直接返回,因为原生销毁上下文时已回收其全部张量。

方法

run()

把非零张量指针归还给所属上下文

由 Cleaner 线程或 close() 触发。取到非零指针后调用 context.releaseTensorQuietly(value),该调用在上下文仍打开时经 Guard 转发到 NativeBindings.releaseTensor,否则静默跳过。

返回

无返回值;不抛出异常