C++23:多维视图(std::mdspan)
  MxWiQzrJEqjh 2023年11月13日 29 0


C++23:多维视图(std::mdspan)

介绍

在 C++23 中,std::mdspan 是一个非拥有的多维视图,用于表示连续对象序列。这个连续对象序列可以是一个简单的 C 数组、带有大小的指针、std::arraystd::vectorstd::string

这种多维视图通常被称为多维数组。

多维数组的形状由其维数(也称为秩)和每个维度的大小(也称为扩展)决定。std::mdspan 的大小是所有非零维度的大小的乘积。你可以使用多维索引运算符 [] 来访问 std::mdspan 的元素。

每个 std::mdspan 的维度可以有静态或动态的扩展。静态扩展意味着其长度在编译时指定;动态扩展意味着其长度在运行时指定。

定义

template<
    class T,
    class Extents,
    class LayoutPolicy = std::layout_right,
    class AccessorPolicy = std::default_accessor<T>
> class mdspan;
  • T: 连续对象序列的类型。
  • Extents: 指定维数及其大小;每个维度可以有静态或动态的扩展。
  • LayoutPolicy: 指定用于访问底层内存的布局策略。
  • AccessorPolicy: 指定如何引用底层元素。

由于 C++17 中的类模板参数推导(CTAD),编译器通常可以自动从初始化器的类型推导出模板参数。

示例

使用动态扩展

#include <mdspan>
#include <iostream>
#include <vector>

int main() {
    
    std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};          // (1)

    std::mdspan m{myVec.data(), 2, 4};                  // (2)
    std::cout << "m.rank(): " << m.rank() << '\n';      // (4)

    for (std::size_t i = 0; i < m.extent(0); ++i) {     // (6)
        for (std::size_t j = 0; j < m.extent(1); ++j) { // (7)
            std::cout << m[i, j] << ' ';                // (8)
        }
        std::cout << '\n';
    }

    std::cout << '\n';

    std::mdspan m2{myVec.data(), 4, 2};                 // (3)
    std::cout << "m2.rank(): " << m2.rank() << '\n';    // (5)

    for (std::size_t i = 0; i < m2.extent(0); ++i) {
        for (std::size_t j = 0; j < m2.extent(1); ++j) {
        std::cout << m2[i, j] << ' ';  
    }
    std::cout << '\n';
  }

}

使用静态和动态扩展

#include <mdspan>
#include <iostream>
#include <string>
#include <vector>
#include <tuple>

int main() {
    
    std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};

    std::mdspan<int, std::extents<std::size_t, 2, 4>> m{myVec.data()}; // (1)
    std::cout << "m.rank(): " << m.rank() << '\n';

    for (std::size_t i = 0; i < m.extent(0); ++i) {
        for (std::size_t j = 0; j < m.extent(1); ++j) {
            std::cout << m[i, j] << ' ';  
        }
        std::cout << '\n';
    }

    std::cout << '\n';

    std::mdspan<int, std::extents<std::size_t, std::dynamic_extent, 
                std::dynamic_extent>> m2{myVec.data(), 4, 2};          // (2)
    std::cout << "m2.rank(): " << m2.rank() << '\n';

    for (std::size_t i = 0; i < m2.extent(0); ++i) {
        for (std::size_t j = 0; j < m2.extent(1); ++j) {
        std::cout << m2[i, j] << ' ';  
    }
    std::cout << '\n';
  }

   std::cout << '\n';

}

布局策略

std::mdspan 允许您指定用于访问底层内存的布局策略。默认情况下,使用 std::layout_right(C、C++ 或 Python 风格),但您也可以指定 std::layout_left(Fortran 或 MATLAB 风格)。

C++23:多维视图(std::mdspan)_算法

使用布局策略std::mdspanstd::layout_right遍历两个std::layout_left可以看出差异。

#include <mdspan>
#include <iostream>
#include <vector>

int main() {
    
    std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};

    std::mdspan<int, std::extents<std::size_t,      // (1)
         std::dynamic_extent, std::dynamic_extent>, 
         std::layout_right> m{myVec.data(), 4, 2};
    std::cout << "m.rank(): " << m.rank() << '\n';

    for (std::size_t i = 0; i < m.extent(0); ++i) {
        for (std::size_t j = 0; j < m.extent(1); ++j) {
            std::cout << m[i, j] << ' ';  
        }
        std::cout << '\n';
    }

    std::cout << '\n';

    std::mdspan<int, std::extents<std::size_t,     // (2)
         std::dynamic_extent, std::dynamic_extent>, 
         std::layout_left> m2{myVec.data(), 4, 2};
    std::cout << "m2.rank(): " << m2.rank() << '\n';

    for (std::size_t i = 0; i < m2.extent(0); ++i) {
        for (std::size_t j = 0; j < m2.extent(1); ++j) {
        std::cout << m2[i, j] << ' ';  
    }
    std::cout << '\n';
  }

}

C++23:多维视图(std::mdspan)_#include_02

接口概览

  • md[ind]: 访问第 ind 个元素。
  • md.size: 返回多维数组的大小。
  • md.rank: 返回多维数组的维数。
  • md.extents(i): 返回第 i 个维度的大小。
  • md.data_handle: 返回指向连续元素序列的指针。

参考:MC++ BLOG – Der Blog für Modernes C++ von Rainer Grimm (modernescpp.com)


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月13日 0

暂无评论

推荐阅读
MxWiQzrJEqjh