在 DPC++ 向量加法中给出更大数组大小的随机退出代码
Random exit code on giving larger array sizes in DPC++ Vector Addition
我正在尝试 运行 oneAPI 的 hello-world DPC++ 示例,它在 CPU 和 GPU 上添加两个一维数组,并验证结果。代码如下:
/*
DataParallel Addition of two Vectors
*/
#include <CL/sycl.hpp>
#include <array>
#include <iostream>
using namespace sycl;
constexpr size_t array_size = 100000;
typedef std::array<int, array_size> IntArray;
// Initialize array with the same value as its index
void InitializeArray(IntArray& a) { for (size_t i = 0; i < a.size(); i++) a[i] = i; }
/*
Create an asynchronous Exception Handler for sycl
*/
static auto exception_handler = [](cl::sycl::exception_list eList) {
for (std::exception_ptr const& e : eList) {
try {
std::rethrow_exception(e);
}
catch (std::exception const& e) {
std::cout << "Failure" << std::endl;
std::terminate();
}
}
};
void VectorAddParallel(queue &q, const IntArray& x, const IntArray& y, IntArray& parallel_sum) {
range<1> num_items{ x.size() };
buffer x_buf(x);
buffer y_buf(y);
buffer sum_buf(parallel_sum.data(), num_items);
/*
Submit a command group to the queue by a lambda
which contains data access permissions and device computation
*/
q.submit([&](handler& h) {
auto xa = x_buf.get_access<access::mode::read>(h);
auto ya = y_buf.get_access<access::mode::read>(h);
auto sa = sum_buf.get_access<access::mode::write>(h);
std::cout << "Adding on GPU (Parallel)\n";
h.parallel_for(num_items, [=](id<1> i) { sa[i] = xa[i] + ya[i]; });
std::cout << "Done on GPU (Parallel)\n";
});
/*
queue runs the kernel asynchronously. Once beyond the scope,
buffers' data is copied back to the host.
*/
}
int main() {
default_selector d_selector;
IntArray a, b, sequential, parallel;
InitializeArray(a);
InitializeArray(b);
try {
// Queue needs: Device and Exception handler
queue q(d_selector, exception_handler);
std::cout << "Accelerator: "
<< q.get_device().get_info<info::device::name>() << "\n";
std::cout << "Vector size: " << a.size() << "\n";
VectorAddParallel(q, a, b, parallel);
}
catch (std::exception const& e) {
std::cout << "Exception while creating Queue. Terminating...\n";
std::terminate();
}
/*
Do the sequential, which is supposed to be slow
*/
std::cout << "Adding on CPU (Scalar)\n";
for (size_t i = 0; i < sequential.size(); i++) {
sequential[i] = a[i] + b[i];
}
std::cout << "Done on CPU (Scalar)\n";
/*
Verify results, the old-school way
*/
for (size_t i = 0; i < parallel.size(); i++) {
if (parallel[i] != sequential[i]) {
std::cout << "Fail: " << parallel[i] << " != " << sequential[i] << std::endl;
std::cout << "Failed. Results do not match.\n";
return -1;
}
}
std::cout << "Success!\n";
return 0;
}
相对较小的 array_size
,(我测试了 100-50k 个元素)计算结果很好。
示例输出:
Accelerator: Intel(R) Gen9
Vector size: 50000
Adding on GPU (Parallel)
Done on GPU (Parallel)
Adding on CPU (Scalar)
Done on CPU (Scalar)
Success!
可以注意到,在 CPU 和 GPU 上完成计算只需要一秒钟。
但是当我增加 array_size
时,也就是说,100000
,我得到了这个看似毫无头绪的错误:
C:\Users\myuser\source\repos\dpcpp-iotas\x64\Debug\dpcpp-iotas.exe (process 24472) exited with code -1073741571.
虽然我不确定错误开始发生的精确值,但我似乎可以肯定它发生在大约 70000
之后。我似乎不知道为什么会这样,对什么地方可能出错有任何见解吗?
事实证明,这是由于 VS 对 Stack size 进行了强化。元素过多的连续数组导致堆栈溢出。
如@user4581301所述,十六进制的错误代码-107374171
给出C00000FD
,这是Visual Studio中'stack exhaustion/overflow'的符号表示。
解决此问题的方法:
- 在“项目属性”>“链接器”>“系统”>“堆栈”Reserve/Commit 值中将
/STACK
保留增加到高于 1MB(这是默认值)。
- 使用二进制编辑器(editbin.exe 和 dumpbin.exe)编辑
/STACK:reserve
。
- 改用
std::vector
,它允许动态分配(@Retired Ninja 建议)。
我在 oneAPI 中找不到更改 /STACK
的选项,链接器属性中的正常方式显示 here。
我决定采用动态分配。
相关:
当我编写大型应用程序时,我总是做
ulimit -s unlimited
向 shell 解释我已经长大了,我真的想要一些 space 在我的堆栈上。
这是 bash
语法,但您显然可以适应其他一些 shell 语法。
我想 non-UNIX OS?
可能有等价物
我正在尝试 运行 oneAPI 的 hello-world DPC++ 示例,它在 CPU 和 GPU 上添加两个一维数组,并验证结果。代码如下:
/*
DataParallel Addition of two Vectors
*/
#include <CL/sycl.hpp>
#include <array>
#include <iostream>
using namespace sycl;
constexpr size_t array_size = 100000;
typedef std::array<int, array_size> IntArray;
// Initialize array with the same value as its index
void InitializeArray(IntArray& a) { for (size_t i = 0; i < a.size(); i++) a[i] = i; }
/*
Create an asynchronous Exception Handler for sycl
*/
static auto exception_handler = [](cl::sycl::exception_list eList) {
for (std::exception_ptr const& e : eList) {
try {
std::rethrow_exception(e);
}
catch (std::exception const& e) {
std::cout << "Failure" << std::endl;
std::terminate();
}
}
};
void VectorAddParallel(queue &q, const IntArray& x, const IntArray& y, IntArray& parallel_sum) {
range<1> num_items{ x.size() };
buffer x_buf(x);
buffer y_buf(y);
buffer sum_buf(parallel_sum.data(), num_items);
/*
Submit a command group to the queue by a lambda
which contains data access permissions and device computation
*/
q.submit([&](handler& h) {
auto xa = x_buf.get_access<access::mode::read>(h);
auto ya = y_buf.get_access<access::mode::read>(h);
auto sa = sum_buf.get_access<access::mode::write>(h);
std::cout << "Adding on GPU (Parallel)\n";
h.parallel_for(num_items, [=](id<1> i) { sa[i] = xa[i] + ya[i]; });
std::cout << "Done on GPU (Parallel)\n";
});
/*
queue runs the kernel asynchronously. Once beyond the scope,
buffers' data is copied back to the host.
*/
}
int main() {
default_selector d_selector;
IntArray a, b, sequential, parallel;
InitializeArray(a);
InitializeArray(b);
try {
// Queue needs: Device and Exception handler
queue q(d_selector, exception_handler);
std::cout << "Accelerator: "
<< q.get_device().get_info<info::device::name>() << "\n";
std::cout << "Vector size: " << a.size() << "\n";
VectorAddParallel(q, a, b, parallel);
}
catch (std::exception const& e) {
std::cout << "Exception while creating Queue. Terminating...\n";
std::terminate();
}
/*
Do the sequential, which is supposed to be slow
*/
std::cout << "Adding on CPU (Scalar)\n";
for (size_t i = 0; i < sequential.size(); i++) {
sequential[i] = a[i] + b[i];
}
std::cout << "Done on CPU (Scalar)\n";
/*
Verify results, the old-school way
*/
for (size_t i = 0; i < parallel.size(); i++) {
if (parallel[i] != sequential[i]) {
std::cout << "Fail: " << parallel[i] << " != " << sequential[i] << std::endl;
std::cout << "Failed. Results do not match.\n";
return -1;
}
}
std::cout << "Success!\n";
return 0;
}
相对较小的 array_size
,(我测试了 100-50k 个元素)计算结果很好。
示例输出:
Accelerator: Intel(R) Gen9
Vector size: 50000
Adding on GPU (Parallel)
Done on GPU (Parallel)
Adding on CPU (Scalar)
Done on CPU (Scalar)
Success!
可以注意到,在 CPU 和 GPU 上完成计算只需要一秒钟。
但是当我增加 array_size
时,也就是说,100000
,我得到了这个看似毫无头绪的错误:
C:\Users\myuser\source\repos\dpcpp-iotas\x64\Debug\dpcpp-iotas.exe (process 24472) exited with code -1073741571.
虽然我不确定错误开始发生的精确值,但我似乎可以肯定它发生在大约 70000
之后。我似乎不知道为什么会这样,对什么地方可能出错有任何见解吗?
事实证明,这是由于 VS 对 Stack size 进行了强化。元素过多的连续数组导致堆栈溢出。
如@user4581301所述,十六进制的错误代码-107374171
给出C00000FD
,这是Visual Studio中'stack exhaustion/overflow'的符号表示。
解决此问题的方法:
- 在“项目属性”>“链接器”>“系统”>“堆栈”Reserve/Commit 值中将
/STACK
保留增加到高于 1MB(这是默认值)。 - 使用二进制编辑器(editbin.exe 和 dumpbin.exe)编辑
/STACK:reserve
。 - 改用
std::vector
,它允许动态分配(@Retired Ninja 建议)。
我在 oneAPI 中找不到更改 /STACK
的选项,链接器属性中的正常方式显示 here。
我决定采用动态分配。
相关:
当我编写大型应用程序时,我总是做
ulimit -s unlimited
向 shell 解释我已经长大了,我真的想要一些 space 在我的堆栈上。
这是 bash
语法,但您显然可以适应其他一些 shell 语法。
我想 non-UNIX OS?
可能有等价物