使用 SYCL 中的类

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

我正在尝试为我正在从事的 SYCL 项目采用 OOP 软件设计策略。

我让我的代码在其 C++ 版本中运行,然后我尝试将其转换为 SYCL,同时尝试使代码可维护和可重用。

我将代码转换为 SYCL,并删除了 C++ 中所有不支持的功能,例如堆内存分配、递归和虚函数。

在编译代码时,遇到以下错误消息:

In file included from sycl_class_test.cpp:1:
In file included from /opt/intel/oneapi/compiler/2023.1.0/linux/bin-llvm/../include/sycl/sycl.hpp:11:
In file included from /opt/intel/oneapi/compiler/2023.1.0/linux/bin-llvm/../include/sycl/accessor.hpp:28:
In file included from /opt/intel/oneapi/compiler/2023.1.0/linux/bin-llvm/../include/sycl/image.hpp:18:
/opt/intel/oneapi/compiler/2023.1.0/linux/bin-llvm/../include/sycl/types.hpp:2443:3: error: static assertion failed due to requirement 'is_device_copyable<MyClass<10>, void>::value || detail::IsDeprecatedDeviceCopyable<MyClass<10>, void>::value': The specified type is not device copyable
  static_assert(is_device_copyable<FieldT>::value ||
  ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

错误信息对于定位问题的作用不大,所以不知道需要修改什么。

我使用一个简单的类示例重现了该错误:

在代码中,我的目标是维护以下功能:

  1. 对其内在成员变量执行操作的类。

  2. 能够操作不同大小的对象,这就是我在课堂上使用模板的原因。

代码附在下面。

#include <iostream>
#include <vector>
#include <array>

template <std::size_t N>
class MyClass {
public:
    MyClass(std::array<float,N> a, std::array<float,N> b) 
        {
            for (std::size_t i = 0; i < N; i++) {
                _a[i] = a[i];
                _b[i] = b[i];
            }
        }
    

    float addValue(int i) const {
        if(i >= N || i >= N)
            //throw std::runtime_error("Index out of bounds");
            return 0;
        return _a[i] + _b[i];
    }

    void modifyAValue(int i, float b) {
        if(i>=N)
            return;
        _a[i] = b;
    }

    void modifyBValue(int i, float b) {
        if(i>=N)
            return;
        _b[i] = b;
    }

    MyClass(const MyClass& other) {
        for (std::size_t i = 0; i < N; i++) {
            _a[i] = other._a[i];
            _b[i] = other._b[i];
        }
    }

private:
    std::array<float, N> _a;
    std::array<float, N> _b;

    //size_t _sizeA;
    //size_t _sizeB;
};

int main() {
    // Create a SYCL queue
    sycl::queue myQueue;

    // Create an instance of MyClass
    int N = 10;
    std::array<float,10> a {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    std::array<float,10> b {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    MyClass<10> myObject(a, b);

    std::vector<int> input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::vector<float> result(input.size());

    // Create a SYCL buffer to hold the result
    sycl::buffer<float, 1> resultBuffer(result.data(), sycl::range<1>(input.size()));
    sycl::buffer<int, 1> inputBuffer(input.data(), sycl::range<1>(input.size()));

    // Submit a SYCL kernel
    myQueue.submit([&](sycl::handler& cgh) {
        auto resultAcc = resultBuffer.template get_access<sycl::access::mode::write>(cgh);
        auto inputAcc = inputBuffer.template get_access<sycl::access::mode::read>(cgh);

        cgh.parallel_for<class MyKernel>(
            sycl::range<1>(input.size()),
            [=](sycl::id<1> idx) {
                // Call a member function on the instance of MyClass
                resultAcc[idx] = myObject.addValue(inputAcc[idx]);
            }
        );
    });

    // Wait for the kernel to complete and get the result
    myQueue.wait();

    // Print the result (accumulated sum)
    float sum = 0.0f;
    for (float val : result) {
        std::cout << val << std::endl;
        sum += val;
    }
    std::cout << "Result: " << sum << std::endl;

    return 0;
}   ```cpp
c++ software-design sycl
1个回答
0
投票

SYCL 对放入缓冲区的类型非常严格,因为它们可能需要复制到设备。一旦您创建了非 Pod 类型,您就必须考虑3.13.1 设备可复制,它规定了可以复制到设备的内容。要实现设备可复制,您的课程必须满足一组要求:

  • 应用程序将特征 is_device_copyable_v 定义为 true;
  • 类型 T 至少有一个符合条件的复制构造函数、移动构造函数、复制赋值运算符或移动赋值运算符;
  • 每个符合条件的复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符都是公共的;
  • 在对 T 类型的对象进行设备间传输时,每个符合条件的复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符的效果与对象的按位复制相同;
  • T 类型有一个公共的非删除析构函数;
  • 析构函数在设备上执行时没有任何效果。

您的班级似乎满足除第一个要求之外的所有要求:

应用程序将特征 is_device_copyable_v 定义为 true;

由于这是自定义类型,因此您必须手动指定。这如4.12.3 所示。 is_device_copyable 类型 Trait 部分。你必须做:

template<>
struct sycl::is_device_copyable<MyClass> : std::true_type {};

为您的自定义类别专门化此特征。在同一个文件中执行此操作,以便人们可以包含它并在任何地方使用它。

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