如何访问使用 omp_target_alloc() 分配的设备内存
How to access device memory which was allocated using omp_target_alloc()
我正在试验OpenMP和目标指令。我使用omp_target_alloc()
直接在设备上分配缓冲区,然后尝试写入target
区域内的此缓冲区。不幸的是,当我尝试这样做时,我遇到了分段错误。有趣的是,如果我使用指令而不是函数omp_target_alloc()
,程序不会崩溃。为了使事情更加有趣,omp_get_num_devices()
和omp_get_default_device()
都返回 0。这是我的代码:
#include <iostream>
#include <omp.h>
//#define USE_TARGET // Uncomment this to see the segmentation fault
int main(int argc, char** argv)
{
const unsigned long int N = 100000;
std::cout << "Number of devices: " << omp_get_num_devices() << std::endl;
std::cout << "Default device: " << omp_get_default_device() << std::endl;
// Allocate
#ifdef USE_TARGET
float* buffer = (float*)omp_target_alloc(N*sizeof(float), 0);
#else
float* buffer = (float*)malloc(N*sizeof(float));
#endif
// Evaluate
#ifdef USE_TARGET
#pragma omp target is_device_ptr(buffer)
{
#else
#pragma omp target data map(tofrom:buffer[0:N])
{
#endif
#pragma omp parallel for
for(unsigned long int i = 0; i < N; ++i)
buffer[i] = i;
}
// Cleanup
#ifdef USE_TARGET
omp_target_free(buffer, 0);
#else
free(buffer);
#endif
return 0;
}
有人可以向我解释为什么上面的代码在我定义USE_TARGET
时会产生分段错误吗?我需要做什么来修复此代码?
我在呼叫omp_target_alloc()
时使用"设备 0"。我假设设备 0 是 CPU 本身。右?我知道target
指令和omp_target_alloc()
有点毫无意义,但我的目标是编写一个同时在加速器和 CPU 上运行的代码。
另外,g++ --version
给了我这个:g++ (Debian 7.3.0-5) 7.3.0
问题是,根据 OpenMP 4.5 规范(请参阅第 3.5.1 节),omp_target_alloc
要求
device_num,必须大于或等于零且小于 omp_get_num_devices() 的结果
在您的情况下,GCC 的安装看不到任何非主机设备,因为omp_get_num_devices()
返回零。这会导致omp_target_alloc
返回NULL
。这就是为什么它崩溃 http://coliru.stacked-crooked.com/a/00054f08e8e1322e
在我的系统上,omp_get_num_devices
返回 1,并且您的代码不会崩溃。
我刚刚了解到我可以通过使用-foffload=disable
让您的代码在我的系统上崩溃
g++ -Wall -O3 -fopenmp -foffload=disable -fno-stack-protector foo.cpp
这将禁用卸载并导致omp_target_alloc
返回NULL
。
您可以使用以下方法修复代码
bool offload;
#pragma omp target defaultmap(tofrom:scalar)
offload = !omp_is_initial_device();
int device = offload ? 0: omp_get_initial_device();
如果没有非主机设备,则会device
主机设备,否则会将设备设置为0
。 我在这里有了这个想法。然后对设备参数使用device
而不是0
,如下所示:
#include <iostream>
#include <omp.h>
int main(int argc, char** argv)
{
const unsigned long int N = 100000;
std::cout << "Number of devices: " << omp_get_num_devices() << std::endl;
std::cout << "Default device: " << omp_get_default_device() << std::endl;
bool offload;
#pragma omp target defaultmap(tofrom:scalar)
offload = !omp_is_initial_device();
int device = offload ? 0: omp_get_initial_device();
if (offload) {
printf("Able to use offloading!n");
}
// Allocate
float* buffer = (float*)omp_target_alloc(N*sizeof(float), device);
// Evaluate
#pragma omp target is_device_ptr(buffer)
#pragma omp parallel for
for(unsigned long int i = 0; i < N; ++i) buffer[i] = i;
// Cleanup
omp_target_free(buffer, device);
return 0;
}
http://coliru.stacked-crooked.com/a/5104446f789e2fc9
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- Win32编译器选项和内存分配
- 函数中堆分配的效果与缺少堆分配的情况
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 获取字符串的长度并将其分配给数组
- 将地址分配给本地指针后,公共对象的变量将消失
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 我在二维向量中是否正确分配了内存
- 正在尝试重载二进制搜索树分配运算符
- GlobalAlloc而不是其他分配方法
- 自定义先决条件对移动分配运算符有效吗
- 我可以重新分配/覆盖std::字符串吗
- 在c++中使用动态分配的问题
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 为什么我可以使用比分配的内存更多的内存
- 组件对象模型 (COM):IMalloc::Alloc 在哪里分配内存?