You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何遍历mdspan?为何一维mdspan无法像span一样用范围for循环?

mdspan无法直接用范围for遍历的原因及解决方法

问题背景

使用std::span时可以直接通过范围for遍历元素:

std::vector vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
auto sp = std::span(vec.data(), 12);
for (auto x : sp) {
    std::cout << x << ' ';
}
std::cout << '\n';

但改用Kokkos实现的std::mdspan时,即使一维场景也会编译报错:

std::vector vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
auto ms = std::mdspan(vec.data(), 12);
for (auto x : ms) {
    std::cout << x << ' ';
}
std::cout << '\n';

报错信息:

<source>:10:19: error: 'begin' was not declared in this scope
   10 |     for (auto x : ms) {
      |                   ^~

原因分析

mdspan的设计初衷是提供多维索引访问能力,而非作为可直接遍历的序列类型。标准mdspan(包括Kokkos的实现)既没有定义begin()/end()成员函数,也没有适配std::begin/std::end的重载。而范围for循环的底层逻辑是通过ADL(参数依赖查找)或std命名空间找到对应的begin和end迭代器,因此无法直接用范围for遍历mdspan。

遍历mdspan的方法

1. 一维mdspan遍历

方法一:转换为std::span

利用mdspan的data()获取底层数据指针,size()获取总元素数,构造std::span后即可用范围for:

std::vector vec = { 1, 2, 3, ..., 12 };
auto ms = std::mdspan(vec.data(), 12);
for (auto x : std::span{ms.data(), ms.size()}) {
    std::cout << x << ' ';
}

方法二:手动索引遍历

直接通过一维索引访问元素:

for (std::size_t i = 0; i < ms.extent(0); ++i) {
    std::cout << ms[i] << ' ';
}

2. 多维mdspan遍历

方式一:扁平化遍历所有元素

同样转成std::span,直接遍历全部元素(按内存存储顺序):

std::vector vec = { 1, 2, ..., 12 };
// 2行6列的二维mdspan
auto ms = std::mdspan(vec.data(), 2, 6);
for (auto x : std::span{ms.data(), ms.size()}) {
    std::cout << x << ' ';
}

方式二:按维度嵌套遍历

按照mdspan的维度层级,嵌套循环逐个访问元素,适合需要保留维度结构的场景:

// 二维mdspan示例
auto ms_2d = std::mdspan(vec.data(), 2, 6);
for (std::size_t row = 0; row < ms_2d.extent(0); ++row) {
    for (std::size_t col = 0; col < ms_2d.extent(1); ++col) {
        std::cout << ms_2d[row, col] << ' ';
    }
    std::cout << '\n'; // 每行结束换行
}
// 三维mdspan示例(2x3x2)
auto ms_3d = std::mdspan(vec.data(), 2, 3, 2);
for (std::size_t i = 0; i < ms_3d.extent(0); ++i) {
    for (std::size_t j = 0; j < ms_3d.extent(1); ++j) {
        for (std::size_t k = 0; k < ms_3d.extent(2); ++k) {
            std::cout << ms_3d[i, j, k] << ' ';
        }
        std::cout << '\n';
    }
    std::cout << "\n---\n";
}

方式三:使用Kokkos并行遍历(针对Kokkos mdspan)

如果是Kokkos的mdspan,还可以利用Kokkos的并行接口实现高效遍历,适合高性能计算场景:

// 二维mdspan并行遍历示例
Kokkos::parallel_for("traverse_mdspan", Kokkos::MDRangePolicy<Kokkos::Rank<2>>({0,0}, {ms_2d.extent(0), ms_2d.extent(1)}),
    [&](std::size_t row, std::size_t col) {
        // 处理ms_2d[row, col]
        std::cout << ms_2d[row, col] << ' ';
    });

内容的提问来源于stack exchange,提问作者einpoklum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 20:42:18