nuget server logo nuget api documents
↑

API Docs / Microsoft.VisualBasic.Runtime / SimdMatrix

SimdMatrix

Full name Microsoft.VisualBasic.Math.SIMD.SimdMatrix Assembly Microsoft.VisualBasic.Runtime Members 42

矩阵级(row-major Double()())批量 SIMD 内核门面。

00 Remarks

SimdEngine / SimdReduce / SimdMath / SimdParallel 都是面向一维连续数组的内核,而 Microsoft.VisualBasic.Math 中的矩阵对象内部数据是 “行数组的数组”(每行是一段连续内存)。这里把矩阵操作按行适配到 一维内核上,避免在每个调用点重复书写 For Each row + 内核分派的样板代码。

为什么按行而不是按列:行是连续内存,可以直接交给 New Vector(Of T)(array, offset) 批量装载;列方向是 strided access, 没有可用的向量化原语。需要列数据时先通过 SimdMatrix.ExtractColumn() 把它变成连续数组。

形状契约:与 SimdEngine 的逐元素内核不同,这里会校验 两个矩阵的行数与每行长度都一致,不一致时抛出 ArgumentException; 因为逐元素内核假设长度一致,缺少这层校验只会导致难以定位的越界访问。

回退:所有内核最终都会经过 SimdEngine.CanVectorize() 检查 SIMDEnvironment.IsEnabled,因此 SIMDConfiguration.disable 仍然是全局有效的逃生开关。

01 Syntax

Microsoft.VisualBasic.Math.SIMD.SimdMatrix

02 Methods

NameOverloadsSummary
RowCount 1 矩阵行数(Nothing 视作 0 行)。
ColumnCount 1 矩阵列数(以第一行的长度为基准)。
CheckAgree 1 校验两个矩阵的行数与每行长度都一致。
NewMatrix 1 分配 [rows, cols] 的矩形容器(每行独立分配,内容未初始化)。
Add 1 逐元素相加:out(i)(j) = a(i)(j) + b(i)(j)
Subtract 1 逐元素相减:out(i)(j) = a(i)(j) - b(i)(j)
Multiply 1 逐元素相乘:out(i)(j) = a(i)(j) * b(i)(j)
Divide 1 逐元素标准相除:out(i)(j) = a(i)(j) / b(i)(j)(0/0 = NaN)。
DivideZeroSafe 1 逐元素相除,且分子为零时结果置零(避免 0/0 产生 Double)。
AddInPlace 1 就地逐元素相加。
SubtractInPlace 1 就地逐元素相减。
MultiplyInPlace 1 就地逐元素相乘。
DivideInPlace 1 就地逐元素相除。
DivideZeroSafeInPlace 1 就地逐元素相除(分子为零则结果置零)。
AddScalar 1 矩阵加标量:out(i)(j) = a(i)(j) + scalar
SubtractScalar 1 矩阵减标量:out(i)(j) = a(i)(j) - scalar
ScalarSubtract 1 标量减矩阵:out(i)(j) = scalar - a(i)(j)
MultiplyScalar 1 数乘:out(i)(j) = scalar * a(i)(j)
DivideScalar 1 矩阵除以标量:out(i)(j) = a(i)(j) / scalar
ScalarDivide 1 标量除以矩阵:out(i)(j) = scalar / a(i)(j)
MultiplyScalarInPlace 1 就地数乘:a(i)(j) = scalar * a(i)(j)
Negate 1 逐元素取负。
Abs 1 逐元素绝对值。
Sqrt 1 逐元素平方根。
Square 1 逐元素平方。
PowScalar 1 逐元素固定次幂:out(i)(j) = a(i)(j) ^ exponent
Pow 1 逐元素幂运算:out(i)(j) = a(i)(j) ^ b(i)(j)
Log 1 逐元素以 base 为底的对数。
Exp 1 逐元素自然指数(无硬件指令,保持标量内核)。
Transpose 1 矩阵转置。
ExtractColumn 1 抽取指定列为一个连续的一维数组。
MultiplyRows 1 按行缩放:out(i)(j) = factors(i) * a(i)(j)
Norm1 1 1-范数:所有列绝对值之和中的最大值。
NormInf 1 无穷范数:所有行绝对值之和中的最大值。
NormF 1 Frobenius 范数:SQRT(SUM(a(i)(j) ^ 2))。
Trace 1 矩阵的迹:主对角线元素之和。
MaxIndex 1 全矩阵最大值及其位置。
MinIndex 1 全矩阵最小值及其位置。
Dot 1 矩阵乘积 A * B:右矩阵预转置 + 行方向并行 + 行内 FMA 点积。
MatrixVector 1 矩阵向量乘积:out(i) = SUM(a(i)(j) * x(j)),使用 FMA 点积。
Rank1Update 1 秩一更新:a(i)(j) += alpha * x(i) * y(j),使用 FMA/AXPY 就地更新。
AxpyInPlace 1 就地 AXPY:y(i) += alpha * x(i),使用 FMA。

03 Members

method RowCount #
RowCount(Double()())

矩阵行数(Nothing 视作 0 行)。

method ColumnCount #
ColumnCount(Double()())

矩阵列数(以第一行的长度为基准)。

method CheckAgree #
CheckAgree(Double()(), Double()(), String, String)

校验两个矩阵的行数与每行长度都一致。

method NewMatrix #
NewMatrix(Int32, Int32)

分配 [rows, cols] 的矩形容器(每行独立分配,内容未初始化)。

method Add #
Add(Double()(), Double()())

逐元素相加:out(i)(j) = a(i)(j) + b(i)(j)

method Subtract #
Subtract(Double()(), Double()())

逐元素相减:out(i)(j) = a(i)(j) - b(i)(j)

method Multiply #
Multiply(Double()(), Double()())

逐元素相乘:out(i)(j) = a(i)(j) * b(i)(j)

method Divide #
Divide(Double()(), Double()())

逐元素标准相除:out(i)(j) = a(i)(j) / b(i)(j)(0/0 = NaN)。

method DivideZeroSafe #
DivideZeroSafe(Double()(), Double()())

逐元素相除,且分子为零时结果置零(避免 0/0 产生 Double)。

method AddInPlace #
AddInPlace(Double()(), Double()())

就地逐元素相加。

method SubtractInPlace #
SubtractInPlace(Double()(), Double()())

就地逐元素相减。

method MultiplyInPlace #
MultiplyInPlace(Double()(), Double()())

就地逐元素相乘。

method DivideInPlace #
DivideInPlace(Double()(), Double()())

就地逐元素相除。

method DivideZeroSafeInPlace #
DivideZeroSafeInPlace(Double()(), Double()())

就地逐元素相除(分子为零则结果置零)。

method AddScalar #
AddScalar(Double()(), Double)

矩阵加标量:out(i)(j) = a(i)(j) + scalar

method SubtractScalar #
SubtractScalar(Double()(), Double)

矩阵减标量:out(i)(j) = a(i)(j) - scalar

method ScalarSubtract #
ScalarSubtract(Double, Double()())

标量减矩阵:out(i)(j) = scalar - a(i)(j)

method MultiplyScalar #
MultiplyScalar(Double()(), Double)

数乘:out(i)(j) = scalar * a(i)(j)

method DivideScalar #
DivideScalar(Double()(), Double)

矩阵除以标量:out(i)(j) = a(i)(j) / scalar

method ScalarDivide #
ScalarDivide(Double, Double()())

标量除以矩阵:out(i)(j) = scalar / a(i)(j)

method MultiplyScalarInPlace #
MultiplyScalarInPlace(Double()(), Double)

就地数乘:a(i)(j) = scalar * a(i)(j)

method Negate #
Negate(Double()())

逐元素取负。

method Abs #
Abs(Double()())

逐元素绝对值。

method Sqrt #
Sqrt(Double()())

逐元素平方根。

method Square #
Square(Double()())

逐元素平方。

method PowScalar #
PowScalar(Double()(), Double)

逐元素固定次幂:out(i)(j) = a(i)(j) ^ exponent

Remarks

指数为 2 / 3 / 4 / 0.5 时会走到向量化的快速路径,其余指数退回标量 ^。

method Pow #
Pow(Double()(), Double()())

逐元素幂运算:out(i)(j) = a(i)(j) ^ b(i)(j)

method Log #
Log(Double()(), Double)

逐元素以 base 为底的对数。

method Exp #
Exp(Double()())

逐元素自然指数(无硬件指令,保持标量内核)。

method Transpose #
Transpose(Double()())

矩阵转置。

Remarks

使用 32x32 分块,把跨行的离散访问收拢成块内的顺序访问以降低 cache miss。 转置本身是纯数据搬运,没有可用的算术指令,因此不使用逐元素内核。

method ExtractColumn #
ExtractColumn(Double()(), Int32)

抽取指定列为一个连续的一维数组。

Remarks

跨行读取是 strided access,没有高效的向量化 gather 原语,因此保持顺序拷贝; 它的价值在于把列数据变成连续内存,让后续的列内积/列范数可以走向量化路径。

method MultiplyRows #
MultiplyRows(Double()(), Double())

按行缩放:out(i)(j) = factors(i) * a(i)(j)

Parameters
NameTypeDescription
factorsDouble()()

长度必须等于矩阵的行数

method Norm1 #
Norm1(Double()())

1-范数:所有列绝对值之和中的最大值。

Remarks

逐行累加绝对值,列方向仍然按 [0, rows) 的顺序累加, 因此结果与原实现逐位一致(不存在归约重排); 累加过程使用就地内核,不需要为每一行生成绝对值临时数组。

method NormInf #
NormInf(Double()())

无穷范数:所有行绝对值之和中的最大值。

method NormF #
NormF(Double()())

Frobenius 范数:SQRT(SUM(a(i)(j) ^ 2))。

Remarks

与原先 Hypot 逐步缩放实现一样具备抗上溢能力:先用 SimdReduce.MaxAbs() 探测矩阵的最大绝对值, 只有当它大到平方和可能上溢时(>= 1E+150)才切换到缩放路径。

常规量级的数据直接累加平方和,因此热路径上没有任何逐行临时数组; 这也让常见的 NormF 调用不再是「每行两次分配」的形态。

method Trace #
Trace(Double()())

矩阵的迹:主对角线元素之和。

method MaxIndex #
MaxIndex(Double()(), Int32, Int32)

全矩阵最大值及其位置。

Remarks

只在严格大于当前最大值时更新位置,因此多个相同最大值时返回第一个出现的位置, 与原逐行逐列扫描的语义一致。空矩阵返回 Double 且位置保持 (0, 0)。

method MinIndex #
MinIndex(Double()(), Int32, Int32)

全矩阵最小值及其位置。

method Dot #
Dot(Double()(), Double()())

矩阵乘积 A * B:右矩阵预转置 + 行方向并行 + 行内 FMA 点积。

Parameters
NameTypeDescription
aDouble()()

左矩阵,形状 m x n

bDouble()()

右矩阵,形状 n x p

method MatrixVector #
MatrixVector(Double()(), Double())

矩阵向量乘积:out(i) = SUM(a(i)(j) * x(j)),使用 FMA 点积。

method Rank1Update #
Rank1Update(Double()(), Double(), Double(), Double)

秩一更新:a(i)(j) += alpha * x(i) * y(j),使用 FMA/AXPY 就地更新。

Parameters
NameTypeDescription
aDouble()()

目标矩阵,形状 m x n

xDouble()

长度 m 的列因子

yDouble()

长度 n 的行因子

alphaDouble

缩放因子;需要做减法时传入负值即可

method AxpyInPlace #
AxpyInPlace(Double, Double(), Double())

就地 AXPY:y(i) += alpha * x(i),使用 FMA。