SYCL USM内存拷贝失效及共享内存段错误问题求助
SYCL新手使用ComputeCpp遇到的向量加法问题
问题描述
我是SYCL新手,用ComputeCpp编写了一个简单的向量加法程序,通过USM分配了3个数组。程序运行无报错,但存在两个异常问题:
- 从设备内存拷贝回主机的结果全为0(主机端运行时结果正确);
- 取消注释共享内存的主机访问代码会触发段错误。
程序代码
#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 ********************************************************************************
问题分析与解决
核心原因
- NVIDIA设备的USM兼容性限制:ComputeCpp在NVIDIA GPU上对USM的支持不完善,尤其是共享内存(
malloc_shared)的主机端直接访问无法正常工作,导致段错误;设备内存到栈数组的拷贝也因USM实现兼容性问题失效。 - 栈内存不可被设备访问:代码中
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
相关产品推荐
相关产品推荐

