【RustyML入门】6.0. 数学工具

6. 数学工具

math 模块是 RustyML 其余部分赖以立足的数值基础。它装着成对距离内核、gemm 支撑的矩阵乘积,以及每个估计器、神经网络层和指标在底层都会调用的确定性并行归约。大多数时候你用着这些原语,却叫不出它们的名字。KNN 用的是距离内核。Dense 层用的是 GEMM。方差计算用的是分块归约。RustyML 把可调用的原语都导出了,当你要实现高层 API 没有覆盖的功能时,就能直接拿来用。可调的那部分原语则暴露出旋钮,供你按自己的硬件来调。模块在 math feature 下编译。machine_learningneural_networkutilsmetrics 中任意一个都会传递性地开启 mathfull 也包含它。只要你用了 RustyML,这些原语就已经编译好了。参见安装与Feature配置

有一条主线贯穿这三节。这些原语并行运行,却保持可复现。每一个都通过把工作量估计与一个校准过的阈值相比较,来决定走串行还是走 rayon。归约无论走哪条路都不会让这个选择改变结果。一次归约逐位一致,不管走哪条路。矩阵乘积在多次运行间可复现,不过策略翻转可能挪动最后几位(见 6.2.4)。正是这个性质,让性能调优与并行里的旋钮可以放心地拧。它也支撑起可复现性与随机种子中的那些保证。往下读之前,你应该已经熟悉 ndarray 的 Array1/Array2 和视图。使用ndarray准备数据讲了你需要的部分。这三节请按顺序读。6.1 和 6.3 给你的是今天就能调用的函数。6.2 更多是在为一个你间接调用的后端提供背景。

6.1. 距离度量

距离度量一节覆盖三个不分配内存、逐行计算的内核:squared_euclidean_distance_rowmanhattan_distance_rowminkowski_distance_row。它还覆盖架在它们之上的 DistanceCalculationMetric 枚举。DistanceCalculationMetric 是 KNN、DBSCAN 和轮廓系数共用的唯一调度器。它把度量方式的选择变成一个运行时的值,而不是写死的 match。内核是快路径,其中欧几里得那个特意跳过了开方。枚举则是更顺手的那条路。从这一节读起。它是本章最能直接上手的部分。

rust 复制代码
use ndarray::array;
use rustyml::math::{DistanceCalculationMetric, squared_euclidean_distance_row};

fn main() {
    let a = array![0.0_f64, 0.0];
    let b = array![3.0_f64, 4.0];

    // 原始内核返回的是*平方*距离------不开方。
    println!("squared: {}", squared_euclidean_distance_row(&a, &b)); // 25.0

    // 调度器会开方,并让度量方式在运行时变化。
    let metric = DistanceCalculationMetric::Euclidean;
    println!("euclidean: {}", metric.distance(a.view(), b.view())); // 5.0
}

6.2. 矩阵乘法

矩阵乘法一节讲解库里每一次稠密乘积背后的 gemmkit 后端。它讲 gemmkit 如何在若干条针对特定形状的专用路径之间取舍。它讲 gemmkit 如何自行判断一次乘积值不值得开线程,以及要开多宽。它还讲为什么矩阵-向量乘积会自成一个成本类别。它解释了"无论由多少 worker 跑出来结果都逐位相同"这件事究竟意味着什么。你很少会直接叫出这一层的名字。它垫在线性模型以及 Dense 层和卷积层底下。与其说这一节在讲一套要调用的 API,不如说是在讲清它的策略。它还点出了哪些旋钮才是归你管的:一个是 rustyml::tuning::matmul 里调用侧的分块策略。另一个是经由它再导出的后端自家那组 GEMMKIT_* 旋钮。当你在意某个模型的吞吐量时,就来读这一节。

6.3. 并行归约

并行归约一节介绍 det_reducedet_reduce_range。这两个是分块折叠函数。它们让求和、点积或分桶累加器得到相同的位,无论跑在一个线程还是所有线程上。裸写一个 par_iter().sum(),会按 rayon 碰巧如何窃取工作来重排浮点加法的次序。这两个辅助函数则把输入切成固定 DET_REDUCE_BLOCK 大小的块。分组方式,连带舍入方式,永远不依赖调度。只要你在自己写并行数值循环、又想要一个不随运行次数或线程数漂移的结果,就用这两个辅助函数。

相关推荐
Mr_liu_6662 分钟前
ns3-gym例子解析_基础例子与wifi例子_DQN(3)
开发语言·c++·python·dqn·ns3
weixin_440730504 分钟前
playwright实战-渠道应用操作
开发语言·前端·python
陈年老古董10 分钟前
Python模拟MapReduce分治思想 | 从单文件统计到大文件拆分聚合 学习笔记
开发语言·hadoop·笔记·python·学习
quantdash_cc10 分钟前
数据 API 的稳定性应该如何长期监控?从量化数据监控体系到 QuantDash 实践
开发语言·python·数据分析·量化交易·股票数据·quantdash
程序员cxuan21 分钟前
为啥 Blender 突然火了?
人工智能·后端·程序员
佳児素花痴╮22 分钟前
C++速通2
开发语言·c++·算法
似水এ᭄往昔26 分钟前
【Qt】--常用控件(输入类控件)
开发语言·qt
IT_陈寒35 分钟前
React的状态更新竟然不是同步的?!坑了我一整天
前端·人工智能·后端
David猪大卫42 分钟前
【C++修炼】异常
开发语言·c++·经验分享·笔记·学习·考研·面试
玖玥拾1 小时前
Lua 基础语法(六)xLua Lua 调用 C# 交互
开发语言·unity·c#·lua