You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SYCL USM内存拷贝失效及共享内存段错误问题求助

SYCL新手使用ComputeCpp遇到的向量加法问题

问题描述

我是SYCL新手,用ComputeCpp编写了一个简单的向量加法程序,通过USM分配了3个数组。程序运行无报错,但存在两个异常问题:

  1. 从设备内存拷贝回主机的结果全为0(主机端运行时结果正确);
  2. 取消注释共享内存的主机访问代码会触发段错误。

程序代码

#include <sycl/sycl.hpp>
#include <iostream>

class vector_addition;
class vector_initialization;

int main() {
    constexpr int size = 10;

    try {
        cl::sycl::queue queue(cl::sycl::gpu_selector{});

        int *result_device = cl::sycl::malloc_device<int>(size , queue);
        int *vec1 = cl::sycl::malloc_shared<int>(size , queue);
        int *vec2 = cl::sycl::malloc_shared<int>(size , queue);

        queue.submit([&](cl::sycl::handler &cgh) {
            cgh.parallel_for<vector_initialization>(
                    size, [=](cl::sycl::id<1> idx) {
                        vec1[idx[0]] = idx[0];
                        vec2[idx[0]] = idx[0] * 2;
                    });
        });
        queue.wait();

        //std::cout << "vec1[1] = " << vec1[1] << std::endl;

        queue.submit([&](cl::sycl::handler &cgh) {
            cgh.parallel_for<class vector_addition>(
                size, [=](cl::sycl::id<1> idx) {
                    result_device[idx[0]] = vec1[idx[0]] + vec2[idx[0]];
                });
        });
        queue.wait();

        int result[size];

        queue.submit([&](cl::sycl::handler &cgh) {
            cgh.memcpy(result, result_device, size * sizeof(int));
        });
        queue.wait();

        for (int i = 0; i < size; i++)
            std::cout << result[i] << " ";

    } catch (cl::sycl::exception& e) {
        std::cerr << "SYCL exception caught: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}

异常现象

  • GPU设备运行输出:0 0 0 0 0 0 0 0 0 0
  • 主机端运行输出:0 3 6 9 12 15 18 21 24 27
  • 取消注释std::cout << "vec1[1] = " << vec1[1] << std::endl;触发段错误

ComputeCpp环境信息

********************************************************************************

ComputeCpp Info (CE 2.11.0 2022/08/08)

SYCL 1.2.1 revision 3

********************************************************************************


Device Info:

Discovered 1 devices matching:
  platform    : <any>
  device type : <any>

--------------------------------------------------------------------------------
Device 0:

  Device is supported                     : UNTESTED - Untested OS
  Bitcode targets                         : spirv64 ptx64 
  CL_DEVICE_NAME                          : NVIDIA GeForce RTX 3050 Ti Laptop GPU
  CL_DEVICE_VENDOR                        : NVIDIA Corporation
  CL_DRIVER_VERSION                       : 525.116.03
  CL_DEVICE_TYPE                          : CL_DEVICE_TYPE_GPU 

If you encounter problems when using any of these OpenCL devices, please consult
this website for known issues:
https://developer.codeplay.com/products/computecpp/ce/guides/platform-support?version=2.11.0

********************************************************************************

问题分析与解决

核心原因

  1. NVIDIA设备的USM兼容性限制:ComputeCpp在NVIDIA GPU上对USM的支持不完善,尤其是共享内存(malloc_shared)的主机端直接访问无法正常工作,导致段错误;设备内存到栈数组的拷贝也因USM实现兼容性问题失效。
  2. 栈内存不可被设备访问:代码中int result[size]是栈上分配的内存,设备端无法直接访问,memcpy操作无法正常完成。

解决办法

方案1:改用Buffer模型(推荐)

Buffer是SYCL的标准内存模型,跨设备兼容性更好,替换后的代码如下:

#include <sycl/sycl.hpp>
#include <iostream>

class vector_addition;
class vector_initialization;

int main() {
    constexpr int size = 10;

    try {
        cl::sycl::queue queue(cl::sycl::gpu_selector{});

        // 使用Buffer替代USM
        cl::sycl::buffer<int, 1> vec1_buf(size);
        cl::sycl::buffer<int, 1> vec2_buf(size);
        cl::sycl::buffer<int, 1> result_buf(size);

        queue.submit([&](cl::sycl::handler &cgh) {
            auto vec1_acc = vec1_buf.get_access<cl::sycl::access::mode::write>(cgh);
            auto vec2_acc = vec2_buf.get_access<cl::sycl::access::mode::write>(cgh);
            cgh.parallel_for<vector_initialization>(
                cl::sycl::range<1>(size), [=](cl::sycl::id<1> idx) {
                    vec1_acc[idx] = idx[0];
                    vec2_acc[idx] = idx[0] * 2;
                });
        });

        queue.submit([&](cl::sycl::handler &cgh) {
            auto vec1_acc = vec1_buf.get_access<cl::sycl::access::mode::read>(cgh);
            auto vec2_acc = vec2_buf.get_access<cl::sycl::access::mode::read>(cgh);
            auto result_acc = result_buf.get_access<cl::sycl::access::mode::write>(cgh);
            cgh.parallel_for<vector_addition>(
                cl::sycl::range<1>(size), [=](cl::sycl::id<1> idx) {
                    result_acc[idx] = vec1_acc[idx] + vec2_acc[idx];
                });
        });

        // 从Buffer读取结果到主机
        auto result_host_acc = result_buf.get_access<cl::sycl::access::mode::read>();
        for (int i = 0; i < size; i++)
            std::cout << result_host_acc[i] << " ";

    } catch (cl::sycl::exception& e) {
        std::cerr << "SYCL exception caught: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}

方案2:调整USM使用方式

如果坚持使用USM,需做以下修改:

  • 用malloc_host分配主机可访问的USM内存,替代栈数组;
  • 访问共享内存前,显式同步设备到主机的数据。

修改后的代码:

#include <sycl/sycl.hpp>
#include <iostream>

class vector_addition;
class vector_initialization;

int main() {
    constexpr int size = 10;

    try {
        cl::sycl::queue queue(cl::sycl::gpu_selector{});

        int *result_device = cl::sycl::malloc_device<int>(size , queue);
        int *vec1 = cl::sycl::malloc_shared<int>(size , queue);
        int *vec2 = cl::sycl::malloc_shared<int>(size , queue);
        // 使用主机USM内存替代栈数组
        int *result_host = cl::sycl::malloc_host<int>(size, queue);

        queue.submit([&](cl::sycl::handler &cgh) {
            cgh.parallel_for<vector_initialization>(
                    size, [=](cl::sycl::id<1> idx) {
                        vec1[idx[0]] = idx[0];
                        vec2[idx[0]] = idx[0] * 2;
                    });
        });
        queue.wait();

        // 显式同步共享内存到主机后再访问
        queue.submit([&](cl::sycl::handler& cgh) {
            cgh.memcpy(vec1, vec1, size * sizeof(int));
        }).wait();
        std::cout << "vec1[1] = " << vec1[1] << std::endl;

        queue.submit([&](cl::sycl::handler &cgh) {
            cgh.parallel_for<class vector_addition>(
                size, [=](cl::sycl::id<1> idx) {
                    result_device[idx[0]] = vec1[idx[0]] + vec2[idx[0]];
                });
        });
        queue.wait();

        queue.submit([&](cl::sycl::handler &cgh) {
            cgh.memcpy(result_host, result_device, size * sizeof(int));
        });
        queue.wait();

        for (int i = 0; i < size; i++)
            std::cout << result_host[i] << " ";

        // 释放USM内存
        cl::sycl::free(result_device, queue);
        cl::sycl::free(vec1, queue);
        cl::sycl::free(vec2, queue);
        cl::sycl::free(result_host, queue);

    } catch (cl::sycl::exception& e) {
        std::cerr << "SYCL exception caught: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}

额外提示

你的NVIDIA设备被标记为“UNTESTED - Untested OS”,说明ComputeCpp在该环境下的兼容性未经过充分验证,USM这类特性容易出现不稳定表现,优先选择Buffer模型能避免多数兼容性问题。

内容的提问来源于stack exchange,提问作者Dmytro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 06:38:08