如何在主机上构建和访问libcu++'<cuda/std/mdspan>

问题描述 投票:0回答:1

libcu++ 2.1.0 包含适用于 c++14 及更高版本的 nvcc 的 mdspan 实现。 我尝试使用 nvcc 12.0 和 libcu++ 2.1.0 实现 cppreference (https://en.cppreference.com/w/cpp/container/mdspan) 中的 mdspan 示例代码

我注意到两个问题。

首先,我无法以与示例中相同的方式构造 mdspan。

构造函数“mdspan”的实例与参数列表不匹配 参数类型有:(int *, int, int)

其次,通过operator[]访问mdspan无法编译

错误:没有运算符“[]”与这些操作数匹配 操作数类型有:cuda::std::__4::mdspan、cuda::std::__4::layout_right、cuda::std::__4::default_accessor> [ std::size_t ]

1。如何在构造函数中指定编译时未知的范围?

2。如何访问mdspan的数据?

下面是我的代码,无法使用

nvcc -Ilibcudacxx-2.1.0/include/ -std=c++17 main.cu -o main
进行编译。

#include <cstddef>
#include <vector>
#include <cstdio>

#include <cuda/std/mdspan>
 
int main()
{
    std::vector v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
 
    //error: no instance of constructor "mdspan" matches the argument list. argument types are: (int *, int, int)
    //auto ms2 = cuda::std::mdspan(v.data(), 2, 6); 
    //auto ms3 = cuda::std::mdspan(v.data(), 2, 3, 2);

    //no compilation error with compile-time extents
    cuda::std::mdspan<int, cuda::std::extents<std::size_t, 2,6>> ms2(v.data()); 
    cuda::std::mdspan<int, cuda::std::extents<std::size_t, 2,3,2>> ms3(v.data()); 
 
    // write data using 2D view
    for (std::size_t i = 0; i != ms2.extent(0); i++)
        for (std::size_t j = 0; j != ms2.extent(1); j++)
            //no operator "[]" matches these operands. operand types are: cuda::std::__4::mdspan<int, cuda::std::__4::extents<std::size_t, 2UL, 6UL>, cuda::std::__4::layout_right, cuda::std::__4::default_accessor<int>> [ std::size_t ]
        ms2[i, j] = i * 1000 + j;
 
    // read back using 3D view
    for (std::size_t i = 0; i != ms3.extent(0); i++)
    {
        printf("slice @ i = %lu\n", i);
        for (std::size_t j = 0; j != ms3.extent(1); j++)
        {
            for (std::size_t k = 0; k != ms3.extent(2); k++)
                printf("%d ",  ms3[i, j, k]);
            printf("\n");
        }
    }
}

c++ cuda
1个回答
4
投票

mdspan
的libcu++实现是基于Kokkos的参考实现,它在自述文件中有一些警告

此实现完全符合 2022 年 7 月投票进入 C++23 草案标准的

mdspan
版本。 当不在 C++23 模式下时,实现会偏离建议,如下所示:

C++20

  • 实现
    operator()
    而不是
    operator[]
    • 请注意,无论是否检测到多维下标支持,您都可以通过定义
      MDSPAN_USE_BRACKET_OPERATOR=[0,1]
      MDSPAN_USE_PAREN_OPERATOR=[0,1]
      来控制可用的运算符。

C++17

  • mdspan 有一个默认构造函数,即使在不应该的情况下(即所有静态范围和默认可构造映射/访问器)
  • 缺少条件显式标记,导致某些构造函数隐式存在
    • 最值得注意的是,您可以隐式地从动态范围转换为静态范围,而在 C++20 模式下则不能
  • layout_left::mapping::stride()
    layout_right::mapping::stride()
    layout_stride::mapping::stride()
    有一个约束,即
    extents_type::rank() > 0
    true
    ,这在 C++17 或 C++14 中未实现。

C++14

  • 推导指南不存在
  • submdspan (P2630) 不可用 - submdspan 的早期变体在 C++14 模式下可在 0.5 版之前使用
  • 基准不可用(它们需要 submdspan)

参考实现使用

operator()
而不是
operator[]
(请参阅上面的“C++20”部分)的原因是
operator[]
具有多个参数 是一个 C++23 功能,因此它可以'不能移植到早期的 C++ 版本。

示例中使用的构造函数是针对 C++17 及更高版本实现的(C++14 没有必要的 CTAD*/推导指南),或者至少有一个 test。对于某些(主机)编译器/版本,CTAD 可能会被关闭,但是有一种替代方法可以在没有 CTAD 的情况下指定动态范围:

int main() { ... // explicit specification of index type and number of dimensions using Ext2D = cuda::std::dextents<int, 2>; auto ms2 = cuda::std::mdspan(v.data(), Ext2D{2, 6}); // alternatively using CTAD for extents as well auto ms3 = cuda::std::mdspan(v.data(), cuda::std::extents{2, 3, 2}); ... }


*CTAD:类模板参数推导

© www.soinside.com 2019 - 2024. All rights reserved.