首页 > 解决方案 > 当 tricycle::device::~device 被调用时,triSYCL 抛出 non_cl_error

问题描述

我正在尝试使用 triSYCL 运行并行 for 循环。这是我的代码:

#define TRISYCL_OPENCL
#define OMP_NUM_THREADS 8
#define BOOST_COMPUTE_USE_CPP11

//standart libraries
#include <iostream>
#include <functional>

//deps
#include "CL/sycl.hpp"

struct Color
{
    float r, g, b, a;

    friend std::ostream& operator<<(std::ostream& os, const Color& c)
    {
        os << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")";
        return os;
    }
};

struct Vertex
{
    float x, y;
    Color color;

    friend std::ostream& operator<<(std::ostream& os, const Vertex& v)
    {
        os << "x: " << v.x << ", y: " << v.y << ", color: " << v.color;
        return os;
    }
};

template<typename T>
T mapNumber(T x, T a, T b, T c, T d)
{
    return (x - a) / (b - a) * (d - c) + c;
}

int windowWidth = 640;
int windowHeight = 720;

int main()
{
    auto exception_handler = [](cl::sycl::exception_list exceptions) {
        for (std::exception_ptr const& e : exceptions)
        {
            try
            {
                std::rethrow_exception(e);
            } catch (cl::sycl::exception const& e)
            {
                std::cout << "Caught asynchronous SYCL exception: " << e.what() << std::endl;
            }
        }
    };

    cl::sycl::default_selector defaultSelector;
    cl::sycl::context context(defaultSelector, exception_handler);
    cl::sycl::queue queue(context, defaultSelector, exception_handler);

        auto* pixelColors = new Color[windowWidth * windowHeight];
        {
            cl::sycl::buffer<Color, 2> color_buffer(pixelColors, cl::sycl::range < 2 > {(unsigned long) windowWidth,
                                                                                        (unsigned long) windowHeight});

            cl::sycl::buffer<int, 1> b_windowWidth(&windowWidth, cl::sycl::range < 1 > {1});
            cl::sycl::buffer<int, 1> b_windowHeight(&windowHeight, cl::sycl::range < 1 > {1});

            queue.submit([&](cl::sycl::handler& cgh) {
                auto color_buffer_acc = color_buffer.get_access<cl::sycl::access::mode::write>(cgh);
                auto width_buffer_acc = b_windowWidth.get_access<cl::sycl::access::mode::read>(cgh);
                auto height_buffer_acc = b_windowHeight.get_access<cl::sycl::access::mode::read>(cgh);

                cgh.parallel_for<class init_pixelColors>(
                        cl::sycl::range<2>((unsigned long) width_buffer_acc[0], (unsigned long) height_buffer_acc[0]),
                        [=](cl::sycl::id<2> index) {
                            color_buffer_acc[index[0]][index[1]] = {
                                    mapNumber<float>(index[0], 0.f, width_buffer_acc[0], 0.f, 1.f),
                                    mapNumber<float>(index[1], 0.f, height_buffer_acc[0], 0.f, 1.f),
                                    0.f,
                                    1.f};
                        });
            });

            std::cout << "cl::sycl::queue check - selected device: "
                      << queue.get_device().get_info<cl::sycl::info::device::name>() << std::endl;
        }//here the error appears 

        delete[] pixelColors;
    return 0;
}

我正在用这个 CMakeLists.txt 文件构建它:

cmake_minimum_required(VERSION 3.16.2)

project(acMandelbrotSet_stackoverflow)

set(CMAKE_CXX_STANDARD 17)

set(SRC_FILES
        path/to/main.cpp
        )
find_package(OpenCL REQUIRED)

set(Boost_INCLUDE_DIR path/to/boost)
include_directories(${Boost_INCLUDE_DIR})

include_directories(path/to/SYCL/include)

set(LIBS PRIVATE ${Boost_LIBRARIES} OpenCL::OpenCL)


add_executable(${PROJECT_NAME} ${SRC_FILES})

set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX _d)
target_link_libraries(${PROJECT_NAME} ${LIBS})

当我尝试运行它时,我收到以下消息:libc++abi.dylib: terminating with uncaught exception of type trisycl::non_cl_errorfrom path/to/SYCL/include/triSYCL/command_group/detail/task.hpp line: 278 function: trisycl::detail::task::get_kernel,消息是:“Cannot use an OpenCL kernel in this context” .

我试图mapNumber在内核中创建一个 lambda ,但这没有任何区别。我还尝试在范围结束之前使用它来捕获错误:

try
{
    queue.wait_and_throw();
} catch (cl::sycl::exception const& e)
{
    std::cout << "Caught synchronous SYCL exception: " << e.what() << std::endl;
}

但除了之前的错误之外,没有任何内容打印到控制台。而且我还尝试进行queue.submit调用事件,然后event.wait()在范围结束之前调用,但输出完全相同。

有没有人知道我还能尝试什么?

标签: c++17sycl

解决方案


问题是 triSYCL 是一个研究项目,它更深入地研究了 SYCL 的某些方面,但并未为最终用户提供全球通用的 SYCL 支持。我刚刚在项目的 README 中澄清了这一点。:-( 可能这里的问题是尚未生成 OpenCL SPIR 内核。所以您需要先从 triSYCL https://github.com/triSYCL/triSYCL/blob/master/编译特定的(旧)Clang & LLVM doc/architecture.rst#trisycl-architecture-for-accelerator。但不幸的是,没有简单的 Clang 驱动程序可以使用所有特定的 Clang 和 LLVM 从 SYCL 源生成内核。正确知道它是由一些特别糟糕的Makefiles(环顾https://github.com/triSYCL/triSYCL/blob/master/tests/Makefile#L360) 而且,即使你能活下来,你也可能会遇到一些错误......

好消息是现在有几个其他的 SYCL 实现更容易使用、更完整且错误更少!:-) 以 ComputeCpp、DPC++ 和 hipSYCL 为例。


推荐阅读