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");
}
}
}
mdspan
的libcu++实现是基于Kokkos的参考实现,它在自述文件中有一些警告:
此实现完全符合 2022 年 7 月投票进入 C++23 草案标准的
版本。 当不在 C++23 模式下时,实现会偏离建议,如下所示:mdspan
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
,这在 C++17 或 C++14 中未实现。true
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});
...
}