在过去的一年左右,我注意到StackOverflow上有一些与C++相关的答案提到了`mdspan`,但实际上我从未在C++代码中见过这些。我尝试在我的C++编译器的标准库目录和C++编码指南中寻找它们,但没有找到。我倒是找到了`std::span`,我猜它们可能是相关的,但具体是什么意思呢?而这个"md"代表什么?
请解释一下这个神秘的实体是什么,以及何时我可能想要使用它。
请解释一下这个神秘的实体是什么,以及何时我可能想要使用它。
mdspan
是std::span
的多维扩展,具有许多(不可避免的)灵活配置选项,可用于内存布局和访问模式。
mdspan
可能是相当复杂的东西(通常比std::span
实现的源代码多大约7倍或更多),我们将从一个简化的描述开始,将高级功能保留在下面进一步讨论。
mdspan<T>
是:
T
的元素)。std::span<T>
的泛化。T
的连续元素序列,被解释为多维数组。struct { T * ptr; size_type extents[d]; }
,带有一些方便的方法(用于在运行时确定的d
维度)。
mdspan
解释布局的示例如果我们有:
std::vector v = {1,2,3,4,5,6,7,8,9,10,11,12};
v
的数据视为一个由12个元素组成的一维数组,类似于它的原始定义。auto sp1 = std::span(v.data(), 12);
auto mdsp1 = std::mdspan(v.data(), 12);
auto mdsp2 = std::mdspan(v.data(), 2, 6 );
// ( 1, 2, 3, 4, 5, 6 ),
// ( 7, 8, 9, 10, 11, 12 )
auto ms3 = std::mdspan(v.data(), 2, 3, 2);
// ( ( 1, 2 ), ( 3, 4 ), ( 5, 6 ) ),
// ( ( 7, 8 ), ( 9, 10 ), ( 11, 12 ) )
虽然 std::span
在 C++20 中已经标准化,但 std::mdspan
还没有。然而,它是 C++23 的一部分,该版本已经接近最终定稿(等待最终投票)。
您已经可以使用一个参考实现。它是美国 Sandia 国家实验室的"Kokkos性能可移植生态系统"的一部分。
mdspan
提供了哪些‘额外功能’?”mdspan
实际上有4个模板参数,不仅仅是元素类型和范围:
template <
class T,
class Extents,
class LayoutPolicy = layout_right,
class AccessorPolicy = default_accessor<ElementType>
>
class mdspan;
dextents<size_t>{ 2, 3, 4 }
,但只在类实例中存储值2
和4
;编译器知道在使用第二个维度时需要插入3
。LayoutPolicy = layout_left
,那么mds[x,y]
将位于mds.data[mds.extent(0) * y + x]
,而不是通常的mds.data[mds.extent(1) * x + y]
。mdspan
重新调整为具有不同维度但相同总大小的另一个mdspan
。mdspan
(例如,从矩阵中取子矩阵)-结果仍然是一个mdspan
!这是因为您可以使用包含这些偏移量的LayoutPolicy
来创建mdspan
。这个功能在C++23中不可用。AccessorPolicy
,您可以使mdspan
实际上拥有它们所引用的数据,无论是个别还是集体。
std::mdspan
提案,已被C++23接受。std::mdspan
页面,位于cppreference.com上。(部分示例参考自这些来源。)