Helper
01 Syntax
02 Methods
| Name | Overloads | Summary |
|---|---|---|
| ParallelOptions | 1 | 依据给定的并行度创建一个 ParallelOptions 对象 |
| TaskBlockSize | 1 | 计算任务分块的大小 |
| TaskBlockCount | 1 | 依据分块大小计算任务块的数量 |
| SumParts | 1 | 串行合并各个任务块的局部累加值 |
| SumColumnParts | 1 | 串行合并各个任务块的局部向量累加值 |
| zeros | 1 | utilitity that creates contiguous vector of zeros of size n |
| L2 | 1 | compute L2 distance between two vectors |
| xtod | 1 | 并行计算两两距离矩阵 |
| ReleaseWorkspace | 1 | 线程私有缓冲区的释放回调(Parallel.For 的 localFinally 需要一个非空委托) |
| QuickSelect | 1 | 在 arr 的前 n 个元素中找出第 k 大的值 |
| d2pSparse | 1 | 每行仅保留 top-k 近邻,构建稀疏的联合概率矩阵 |
| ProcessRow | 1 | 处理第 i 行:现算(或读取)距离 → beta 二分搜索 → top-k 选择 → 双向展开写入 |
| EmitPair | 1 | 把 (i, j, v) 双向写入键/值数组,同时完成 (p_{j|i} + p_{i|j}) 的对称化展开 |
| d2p | 1 | compute (p_{i|j} + p_{j|i})/(2n) |
| ReleaseRowBuffer | 1 | 线程私有缓冲区的释放回调 |
| SearchPrecision | 1 | 对第 i 行执行 beta 二分搜索,把最终的条件概率写入 P 的第 i 行 |
| Symmetrize | 1 | symmetrize P and normalize it to sum to 1 over all ij |
03 Members
Int32)依据给定的并行度创建一个 ParallelOptions 对象
| Name | Type | Description |
|---|---|---|
nthreads | Int32 | 并行线程数,小于等于 0 时表示不限制(交由 TPL 的线程池自行调度) |
Int32, Int32, Int32)计算任务分块的大小
归约(qsum / cost / Z / ymean)采用「连续分块 + 每块一个局部累加器 + 按块序串行合并」 的方式,而不是 Parallel.For(Of TLocal) + Interlocked: 省掉了每个元素一次的委托调用与原子操作开销。
分块方案刻意只取决于任务总量而与线程数无关,这带来两个好处: 一是浮点累加的分组方式是固定的,因此同一个数据集在同一台机器上 无论把 nthreads 设成多少,结果都逐位一致(可复现性); 二是任务块数量远多于线程数,TPL 的动态调度可以自动填平 三角循环(第 i 行的工作量随 i 增大而减小)带来的负载不均。
命名为 TaskBlockSize 而不是 BlockSize,是为了避免与调用方常见的 局部变量名 blockSize 相冲突(VB 是大小写不敏感的)。
| Name | Type | Description |
|---|---|---|
total | Int32 | 任务总量 |
maxBlocks | Int32 | 任务块数量的上界 |
minItems | Int32 | 单个任务块的元素数量下界,用于避免把任务切得过碎导致调度开销反超收益 |
Int32, Int32)依据分块大小计算任务块的数量
| Name | Type | Description |
|---|---|---|
total | Int32 | - |
blockSize | Int32 | - |
Double())串行合并各个任务块的局部累加值
Double()(), Int32)串行合并各个任务块的局部向量累加值
放在独立的函数里而不是就地展开,是为了避免 VB 大小写不敏感导致的 循环变量与外层局部变量(例如 d 与 D)重名的编译错误。
| Name | Type | Description |
|---|---|---|
parts | Double()() | - |
[dim] | Int32 | - |
Int32)utilitity that creates contiguous vector of zeros of size n
| Name | Type | Description |
|---|---|---|
n | Int32 | - |
Double(), Double())compute L2 distance between two vectors
| Name | Type | Description |
|---|---|---|
x1 | Double() | - |
x2 | Double() | - |
Double()(), Int32)并行计算两两距离矩阵
按外层行 i 分派。第 i 个任务只写第 i 行与第 i 列(三角对称), 不同的 i 之间所写入的单元格集合互不相交,因此无需加锁。
| Name | Type | Description |
|---|---|---|
X | Double()() | - |
nthreads | Int32 | 并行线程数,<=0 表示不限制 |
线程私有缓冲区的释放回调(Parallel.For 的 localFinally 需要一个非空委托)
Double(), Int32, Int32)在 arr 的前 n 个元素中找出第 k 大的值
3-way 快排选择,平均 O(n),用于避免对每一行做 O(n log n) 的全排序
| Name | Type | Description |
|---|---|---|
arr | Double() | 会被就地分区打乱,调用前请自行备份 |
n | Int32 | - |
k | Int32 | 0-based,0 表示最大值 |
Double, Double, Int32, Int32, Double()(), Double())每行仅保留 top-k 近邻,构建稀疏的联合概率矩阵
这个函数全程不物化 N×N 的稠密概率矩阵,是 Barnes-Hut 模式得以突破 O(N²) 内存墙的关键。
走 X 分支时,连 N×N 的距离矩阵都不需要物化 (每一行在用到时才现算,用完即弃,内存占用仅 threads × N); 走 D 分支时距离矩阵由调用方提供,但概率矩阵依然是稀疏的。
对称化采用「双向展开」而非字典合并:对于每一行的第 m 个近邻 j, 分别写入 (i, j, p{j|i}) 与 (j, i, p{j|i})。 于是对于无序对 {i, j},行 i 上会同时收到 p{j|i}(来自行 i 自身的近邻表)与 p{i|j}(来自行 j 的近邻表所展开出的反向条目),两者相加恰好等于 联合概率定义中的 (p{j|i} + p{i|j}),因此无需再做一次 O(nnz) 的合并去重。
| Name | Type | Description |
|---|---|---|
perplexity | Double | 困惑度 |
tol | Double | beta 二分搜索的收敛容差 |
k | Int32 | 每一行保留的近邻数量 |
nthreads | Int32 | 并行线程数 |
X | Double()() | 高维原始数据;与 D 二者必须恰好提供一个 |
D | Double() | 预先计算好的 N×N 距离矩阵;与 X 二者必须恰好提供一个 |
Double()(), Double(), Int32, Int32, Double, Double, Int32, RowWorkspace, Int64(), Double())处理第 i 行:现算(或读取)距离 → beta 二分搜索 → top-k 选择 → 双向展开写入
Int64(), Double(), Int32, Int32, Int32, Int32, Double)把 (i, j, v) 双向写入键/值数组,同时完成 (p{j|i} + p{i|j}) 的对称化展开
Double(), Double, Double, Int32)compute (p{i|j} + p{j|i})/(2n)
| Name | Type | Description |
|---|---|---|
D | Double() | distance matrix |
perplexity | Double | - |
tol | Double | - |
Double())线程私有缓冲区的释放回调
Double(), Double(), Int32, Int32, Double, Double, Double())对第 i 行执行 beta 二分搜索,把最终的条件概率写入 P 的第 i 行
Double(), Int32, Int32)symmetrize P and normalize it to sum to 1 over all ij
第 i 个任务只写输出矩阵的第 i 行,行与行之间互不相交,可安全并行。
| Name | Type | Description |
|---|---|---|
P | Double() | 稠密的条件概率矩阵,行主序 |
N | Int32 | - |
nthreads | Int32 | 并行线程数 |
对称化之后的联合概率矩阵