如何在主机上构建和访问`libcu++`的``。

huangapple go评论105阅读模式
英文:

How to construct and access libcu++' <cuda/std/mdspan> on the host

问题

libcu++ 2.1.0 包含了针对 nvcc 支持的 C++14 及更高版本的 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<int,cuda::std::__4::extents<std::size_t,2UL,3UL,2UL>,cuda::std::__4::layout_right,cuda::std::__4::default_accessor<int>> [std::size_t]

1. 如何在构造函数中指定在编译时未知的 extent?

2. 如何访问 mdspan 的数据?

以下是我的代码,使用 nvcc -Ilibcudacxx-2.1.0/include/ -std=c++17 main.cu -o main 编译时无法通过:

#include &lt;cstddef&gt;
#include &lt;vector&gt;
#include &lt;cstdio&gt;

#include &lt;cuda/std/mdspan&gt;
 
int main()
{
    std::vector v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
 
    // 错误:没有与参数列表匹配的“mdspan”构造函数实例。参数类型为:(int*,int,int)
    // auto ms2 = cuda::std::mdspan(v.data(), 2, 6); 
    // auto ms3 = cuda::std::mdspan(v.data(), 2, 3, 2);

    // 编译时 extent 不会出错
    cuda::std::mdspan&lt;int, cuda::std::extents&lt;std::size_t, 2,6&gt;&gt; ms2(v.data()); 
    cuda::std::mdspan&lt;int, cuda::std::extents&lt;std::size_t, 2,3,2&gt;&gt; ms3(v.data()); 
 
    // 使用 2D 视图写入数据
    for (std::size_t i = 0; i != ms2.extent(0); i++)
        for (std::size_t j = 0; j != ms2.extent(1); j++)
            // 没有匹配这些操作数的运算符“[]”。操作数类型为:cuda::std::__4::mdspan&lt;int, cuda::std::__4::extents&lt;std::size_t, 2UL, 6UL&gt;, cuda::std::__4::layout_right, cuda::std::__4::default_accessor&lt;int&gt;&gt; [std::size_t]
            ms2[i, j] = i * 1000 + j;
 
    // 使用 3D 视图读取数据
    for (std::size_t i = 0; i != ms3.extent(0); i++)
    {
        printf("在 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");
        }
    }
}

希望这些信息能帮助你解决问题。

英文:

libcu++ 2.1.0 includes an mdspan implementation for nvcc for c++14 and later.
I tried to implement the mdspan sample code from cppreference (https://en.cppreference.com/w/cpp/container/mdspan) with nvcc 12.0 and libcu++ 2.1.0

I noticed two problems.

First, I am unable to construct the mdspan in the same way as in the example.
>no instance of constructor "mdspan" matches the argument list
argument types are: (int *, int, int)

Second, the access to mdspan via operator[] does not compile
> error: no operator "[]" matches these operands
operand types are: cuda::std::__4::mdspan<int, cuda::std::__4::extents<std::size_t, 2UL, 3UL, 2UL>, cuda::std::__4::layout_right, cuda::std::__4::default_accessor<int>> [ std::size_t ]

1. How does one specify an extent in the constructor which is not known at compile-time?

2. How to access the data of mdspan?

Below is my code which does not compile with nvcc -Ilibcudacxx-2.1.0/include/ -std=c++17 main.cu -o main .

#include &lt;cstddef&gt;
#include &lt;vector&gt;
#include &lt;cstdio&gt;

#include &lt;cuda/std/mdspan&gt;
 
int main()
{
    std::vector v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
 
    //error: no instance of constructor &quot;mdspan&quot; 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&lt;int, cuda::std::extents&lt;std::size_t, 2,6&gt;&gt; ms2(v.data()); 
    cuda::std::mdspan&lt;int, cuda::std::extents&lt;std::size_t, 2,3,2&gt;&gt; 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 &quot;[]&quot; matches these operands. operand types are: cuda::std::__4::mdspan&lt;int, cuda::std::__4::extents&lt;std::size_t, 2UL, 6UL&gt;, cuda::std::__4::layout_right, cuda::std::__4::default_accessor&lt;int&gt;&gt; [ 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(&quot;slice @ i = %lu\n&quot;, i);
        for (std::size_t j = 0; j != ms3.extent(1); j++)
        {
            for (std::size_t k = 0; k != ms3.extent(2); k++)
                printf(&quot;%d &quot;,  ms3[i, j, k]);
            printf(&quot;\n&quot;);
        }
    }
}



</details>


# 答案1
**得分**: 3

`mdspan`的`libcu++`实现基于Kokkos的参考实现,Kokkos在自述文件中有一些注意事项:

&gt; 此实现与C++23草案标准中于2022年7月投票通过的`mdspan`版本完全一致。
当不处于C++23模式时,该实现与提案有以下不同:
&gt;
&gt; ### C++20
&gt; - 实现了`operator()`而不是`operator[]`
&gt;   - 请注意,您可以通过定义`MDSPAN_USE_BRACKET_OPERATOR=[0,1]`和`MDSPAN_USE_PAREN_OPERATOR=[0,1]`来控制可用的运算符,而不管是否检测到多维子脚本支持。
&gt;
&gt; ### C++17
&gt; - 即使在不应该的情况下(即所有静态范围和默认可构造的映射/访问器),mdspan都有默认构造函数。
&gt; - 缺少条件显式标记,使某些构造函数变得隐式
&gt;   - 特别是您可以隐式地从动态范围转换为静态范围,在C++20模式下不能这样做。
&gt; - 对于`layout_left::mapping::stride()`、`layout_right::mapping::stride()`和`layout_stride::mapping::stride()`存在一个约束条件,即`extents_type::rank() > 0`为`true`,而在C++17或C++14中没有实现。
&gt;
&gt; ### C++14
&gt; - 没有模板参数推导指南
&gt; - submdspan(P2630)不可用 - 在C++14模式下,可以使用早期版本的submdspan直到0.5版本
&gt; - 没有可用的基准测试(它们需要submdspan)

参考实现之所以使用`operator()`而不是`operator[]`(请参阅上面的“C++20”部分),是因为**带有多个参数的`operator[]`是C++23的特性**,因此无法移植到较早的C++版本中。

示例中使用的构造函数适用于C++17及更高版本(C++14没有必要的CTAD*/模板参数推导指南),或者至少它们对其进行了[测试][4]。对于某些(主机)编译器/版本,CTAD可能会被[禁用][5],但也有[另一种方法][6]可以在没有CTAD的情况下指定动态范围:

```c++
constexpr auto dyn = cuda::std::dynamic_extent;

int main() {
    ...
    using ext_t = cuda::std::extents<int, dyn, dyn>;
    cuda::std::mdspan<int, ext_t> ms2{ v.data(), ext_t{2, 6} };
    ...
}

*CTAD:模板参数类推导(Class Template Argument Deduction)

英文:

The libcu++ implementation of mdspan is based on the reference implementation by Kokkos which has some caveats in the readme:

> This implementation is fully conforming with the version of mdspan voted into the C++23 draft standard in July 2022.
When not in C++23 mode the implementation deviates from the proposal as follows:
>
> ### C++20
> - implements operator() not operator[]
> - note you can control which operator is available with defining MDSPAN_USE_BRACKET_OPERATOR=[0,1] and MDSPAN_USE_PAREN_OPERATOR=[0,1] irrespective of whether multi dimensional subscript support is detected.
>
> ### C++17
> - mdspan has a default constructor even in cases where it shouldn't (i.e. all static extents, and default constructible mapping/accessor)
> - the conditional explicit markup is missing, making certain constructors implicit
> - most notably you can implicitly convert from dynamic extent to static extent, which you can't in C++20 mode
> - there is a constraint on layout_left::mapping::stride(), layout_right::mapping::stride() and layout_stride::mapping::stride() that extents_type::rank() &gt; 0 is true, which is not implemented in C++17 or C++14.
>
> ### C++14
> - deduction guides don't exist
> - submdspan (P2630) is not available - an earlier variant of submdspan is available up to release 0.5 in C++14 mode
> - benchmarks are not available (they need submdspan)

The reason for the reference implementation using operator() instead of operator[] (see section "C++20" above) is that operator[] with multiple arguments is a C++23 feature so it can't be ported to earlier C++ versions.

The constructor that is used in the sample is implemented for C++17 and later (C++14 does not have the necessary CTAD*/deduction guides), or at least they have a test for it. CTAD might be turned off for some (host-) compilers/versions, but there is an alternative way of specifying dynamic extents without CTAD:

constexpr auto dyn = cuda::std::dynamic_extent;

int main() {
    ...
    using ext_t = cuda::std::extents&lt;int, dyn, dyn&gt;;
    cuda::std::mdspan&lt;int, ext_t&gt; ms2{ v.data(), ext_t{2, 6} };
    ...
}

*CTAD: Class Template Argument Deduction

huangapple
  • 本文由 发表于 2023年6月26日 04:41:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76552323.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定