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

如何从连续内存位置直接获取C++ mdspan的张量索引?

从mdspan连续内存位置反向获取张量索引的实现方案

你已经实现了从mdspan张量索引获取连续内存位置的功能,现在需要反向操作:给定内存偏移位置,直接获取对应的张量索引,无需手动进行算术计算。目前标准C++23的std::mdspan并没有内置类似indices_from_pos的方法,但可以利用mdspan的布局映射工具自己实现一个通用解决方案。

原代码示例

#include <https://raw.githubusercontent.com/kokkos/mdspan/single-header/mdspan.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
#include <ranges>

int main(){
    std::vector vec = {1, 2, 3, 4, 5, 6, 7, 88, 9, 10, 11, 12};
    auto ms = std::mdspan(vec.data(), 2, 6);

//已知张量索引,获取连续内存中的位置
    {
        const int position = std::distance(vec.data(), &ms[1, 3]);
        std::cout << position << '\n';
    }
//已知连续内存中的位置,如何直接获取张量索引?
    {
        const int position = 9;
        //我希望避免手动进行算术计算,有没有类似 auto [i, j] = ms.indices_from_pos(position) 的方法?
    }
}

实现通用的indices_from_pos函数

下面的模板函数支持任意维度的mdspan,兼容默认的行优先(layout_right)、列优先(layout_left)等连续内存布局:

#include <tuple>
#include <mdspan>
#include <utility>

// 内部实现:按维度序列计算每个索引
template<class Mdspan, std::size_t... Is>
auto indices_from_pos_impl(const Mdspan& ms, typename Mdspan::index_type pos, std::index_sequence<Is...>) {
    auto mapping = ms.mapping();
    auto strides = mapping.strides();
    
    typename Mdspan::index_type remaining = pos;
    return std::make_tuple(
        [&]<std::size_t I>() {
            auto idx = remaining / strides[I];
            remaining %= strides[I];
            return idx;
        }.template operator()<Is>()...
    );
}

// 对外接口:自动推导维度序列
template<class Mdspan>
auto indices_from_pos(const Mdspan& ms, typename Mdspan::index_type pos) {
    using indices_seq = std::make_index_sequence<Mdspan::rank()>;
    return indices_from_pos_impl(ms, pos, indices_seq{});
}

在主函数中使用

修改原代码的对应部分,即可直接获取张量索引:

//已知连续内存中的位置,获取张量索引
{
    const int position = 9;
    auto [i, j] = indices_from_pos(ms, position);
    std::cout << "对应的张量索引:(" << i << ", " << j << ")\n"; // 输出 (1, 3)
}

说明

  • 该函数通过mdspan的mapping()获取布局的strides(各维度的内存步长),反向计算每个维度的索引,完全避免手动硬编码算术逻辑。
  • 支持任意维度的mdspan,只要布局是连续内存的(非稀疏布局)。
  • 注意:参数pos必须是相对于mdspan起始地址的偏移量(即std::distance(ms.data_handle(), 目标地址)的结果),如果是全局内存地址,需要先转换为相对偏移。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 21:58:23