c++26新功能—线性代数库
·
一、BLAS
BLAS(Basic Linear Algebra Subprograms),基本线性代数子程序。对于一般的开发者来说,可能这个东西几乎上遇不到的。但对于进行科学计算和搞AI的开发者,可能就经常遇得到,而且他们还非常迫切的能有标准库的支持。但大家对C++标准的发展应该是很明白的,不可能对某项专业的技术进行快速的支持。
但随着AI的迅猛发展,标准的大佬们终于不是坐不住了,在库的底层就将其支持了,即将要分析的std::linalg库。std::linalg库遵循BLAS的分层设计实现了代数库的支持即向量运算、矩阵-向量运算和矩阵-矩阵运算。
二、std::linalg库
std::linalg库以BLAS标准的三层体现为:
- BLAS 1级:向量运算(点积、范数、缩放等),时间复杂度 O(n)
std::vector<double> x = {1, 2, 3};
auto norm = std::linalg::vector_norm(x); // 欧几里得范数计算
- BLAS 2级:矩阵-向量运算(矩阵乘向量、三角求解等),时间复杂度 O(n²)
std::mdspan A(A_data, N, N);
std::mdspan x(x_data, N);
std::linalg::matrix_vector_product(A, x, y); // y = A*x
- BLAS 3级:矩阵-矩阵运算(矩阵乘法、秩更新等),时间复杂度 O(n³)
std::linalg::matrix_product(A, B, C); // C = A*B
在linalg库中,在前面分析过的std::mdspan与代数操作进行了深度的集成,特别是在处理矩阵和向量操作时,提供了更加灵活的内存以及异构数据的操作。同时,linalg库还提供了一些接口,实现了一些数学操作零拷贝视图。比如矩阵转置的transposed_view()等。
std::linalg库有以下几个特点:
- 性能高成本低:通过模板元编程和编译期的优化,确保对并行的支持和代码的性能最佳
- 支持SIMD指令:尽可能的降低了对特定厂商和平台的依赖
- 提供数据结构支持和布局控制:如提到的std::mdspan以及相关的内存布局的相关控制
代数库虽好,但确实是对广大的普通开发者来说,没啥应用的场景。所以这里就简单介绍一下,有兴趣的同学们可以自行的查看相关的资料。
三、例程
先看一个基础的Scale的例程:
using Vec = mdspan<double, dextents<size_t, 1>>;
// z = alpha * x + y
void z_equals_alpha_times_x_plus_y(
double alpha, Vec x,
Vec y,
Vec z)
{
add(scaled(alpha, x), y, z);
}
// z = alpha * x + beta * y
void z_equals_alpha_times_x_plus_beta_times_y(
double alpha, Vec x,
double beta, Vec y,
Vec z)
{
add(scaled(alpha, x), scaled(beta, y), z);
}
再看一个矩阵原地转置的例程:
void test_conjugate_transposed(
mdspan<complex<double>, extents<size_t, 3, 4>> a)
{
const auto num_rows = a.extent(0);
const auto num_cols = a.extent(1);
auto a_ct = conjugate_transposed(a);
assert(num_rows == a_ct.extent(1));
assert(num_cols == a_ct.extent(0));
assert(a.stride(0) == a_ct.stride(1));
assert(a.stride(1) == a_ct.stride(0));
for(size_t row = 0; row < num_rows; ++row) {
for(size_t col = 0; col < num_rows; ++col) {
assert(a[row, col] == conj(a_ct[col, row]));
}
}
auto a_ct_ct = conjugate_transposed(a_ct);
assert(num_rows == a_ct_ct.extent(0));
assert(num_cols == a_ct_ct.extent(1));
assert(a.stride(0) == a_ct_ct.stride(0));
assert(a.stride(1) == a_ct_ct.stride(1));
for(size_t row = 0; row < num_rows; ++row) {
for(size_t col = 0; col < num_rows; ++col) {
assert(a[row, col] == a_ct_ct[row, col]);
assert(conj(a_ct[col, row]) == a_ct_ct[row, col]);
}
}
}
在C++26的linalg库中有不少的类似的代数运算支持的接口,也算是相关人员的一个福音。
四、总结
做为初代的代数库的支持版本,std::linalg肯定还是有不和的不足之处。不过从C++标准的演进的过程来看,一旦进入标准后,标准就会不断的吸取其它各方的先进经验,不断的在新版本的标准中进行完善和升级。所以,这是一个好现象,搞科学计算和人工智能的小伙伴应该可以更高兴的看到一个不错的工具递到了眼前。
更多推荐


所有评论(0)