- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我在我的代码中经常使用 thrust,因为它是一个很棒的包装器并提供了非常有用的实用程序,因为添加了对异步行为的支持,我更加确信。
在我最近尝试在我的应用程序中添加多 GPU 支持之前,我的代码使用 cuda thrust 运行良好。我经历了烦人的事
CUDA Runtime API error 77 : an illegal memory access was encountered
我的部分代码以前从未出现过任何边界问题。
我在我的代码中添加了冗长的代码,看起来我的 thrust::device_vector 指针地址在执行过程中发生了变化,没有明显的原因,在手写内核中生成了错误 77。
我可能误解了 UVA 概念及其最终的“副作用”,但我仍然有兴趣了解导致指针更新的过程。
我无法准确重现我的问题,其中我没有使用临时主机变量来存储 cuda 内存指针,而是仅在内核包装器调用需要时即时使用 thrust::raw_pointer_cast。
但我已经编写了一个小程序来显示我可能遇到的错误类型,请注意这并不可靠,您的系统上至少需要有 2 个 gpu 才能运行它:
/********************************************************************************************
** Compile using nvcc ./test.cu -gencode arch=compute_35,code=sm_35 -std=c++11 -o test.exe **
********************************************************************************************/
//Standard Library
#include <iostream>
#include <vector>
//Cuda
#include "cuda_runtime.h"
//Thrust
#include <thrust/device_vector.h>
#include <thrust/functional.h>
#include <thrust/transform.h>
inline void __checkCudaErrors( cudaError err, const char *file, const int line )
{
if( err != cudaSuccess )
{
printf("%s(%i) : CUDA Runtime API error %i : %s \n",file ,line, (int)err, cudaGetErrorString(err) );
}
};
#define checkCudaErrors(err) __checkCudaErrors (err, __FILE__, __LINE__)
__global__ void write_memory( float* buf, float value )
{
printf("GPU TALK: Raw pointer is %p \n",buf);
buf[0] = value;
}
int main( int argc, char* argv[] )
{
//declare a vector of vector
std::vector<thrust::device_vector<float> > v;
float test;
float* tmp;
//Initialize first vector on GPU 0
cudaSetDevice( 0 );
v.emplace_back( 65536, 1.0f );
tmp = thrust::raw_pointer_cast( v.at(0).data() );
std::cout << " Host TALK: Raw pointer of vector 0 at step 0 " << (void*)tmp << std::endl;
//Try to use it raw pointer
write_memory<<<1,1,0,0>>>( tmp, 2.0f );
checkCudaErrors( cudaStreamSynchronize( NULL ) );
test = v.at(0)[0];
std::cout << " Host TALK: After first kernel launch, value is " << test << std::endl;
//Initialize second vector on GPU 1, but we do not use it
cudaSetDevice( 1 );
v.emplace_back( 65536, 1.0f );
std::cout << " Host TALK: Raw pointer of vector 0 at step 1 is now " << (void*)thrust::raw_pointer_cast( v.at(0).data() ) << " != " << (void*)tmp << std::endl;
std::cout << " Host TALK: Raw pointer of vector 1 at step 1 is " << (void*)thrust::raw_pointer_cast( v.at(1).data() ) << std::endl;
//Try to use the first vector : No segmentation fault ?
test = v.at(0)[0];
std::cout << " Host TALK: Before second kernel launch, value is " << test << std::endl;
write_memory<<<1,1,0,0>>>( thrust::raw_pointer_cast( v.at(0).data() ), 3.0f );
checkCudaErrors( cudaStreamSynchronize( NULL ) );
test = v.at(0)[0];
std::cout << " Host TALK: After second kernel launch, value is " << test << std::endl;
//Raw pointer stored elsewhere: generates a segmentation fault
write_memory<<<1,1,0,0>>>( tmp, 4.0f );
checkCudaErrors( cudaStreamSynchronize( NULL ) );
test = v.at(0)[0];
std::cout << " Host TALK: After third kernel launch, value is " << test << std::endl;
return 0;
}
这是它在我的机器上产生的输出示例:
主机对话:第 0 步 vector 0 的原始指针 0xb043c0000
GPU 对话:原始指针是 0xb043c0000
Host TALK:第一次内核启动后,值为 2
主机对话:第 1 步 vector 0 的原始指针现在是 0xb08000000 != 0xb043c0000
主机对话:第 1 步 vector 1 的原始指针是 0xb07fc0000
Host TALK:在第二次内核启动之前,值为 2
GPU 对话:原始指针是 0xb08000000
Host TALK:第二次内核启动后,值为 3
GPU 对话:原始指针是 0xb043c0000
./test.cu(68):CUDA 运行时 API 错误 77:遇到非法内存访问 在抛出“thrust::system::system_error”实例后调用终止 what():遇到非法内存访问
在此先感谢您的帮助,我也可能会在 thrust 的 github 上问这个问题。
编辑:感谢 m.s 和 Hiura,这是一个按预期工作的代码:
/********************************************************************************************
** Compile using nvcc ./test.cu -gencode arch=compute_35,code=sm_35 -std=c++11 -o test.exe **
********************************************************************************************/
//Standard Library
#include <iostream>
#include <vector>
//Cuda
#include "cuda_runtime.h"
//Thrust
#include <thrust/device_vector.h>
#include <thrust/functional.h>
#include <thrust/transform.h>
inline void __checkCudaErrors( cudaError err, const char *file, const int line )
{
if( err != cudaSuccess )
{
printf("%s(%i) : CUDA Runtime API error %i : %s \n",file ,line, (int)err, cudaGetErrorString(err) );
}
};
#define checkCudaErrors(err) __checkCudaErrors (err, __FILE__, __LINE__)
__global__ void write_memory( float* buf, float value )
{
printf("GPU TALK: Raw pointer is %p \n",buf);
buf[0] = value;
}
int main( int argc, char* argv[] )
{
//declare a vector of vector
std::vector<thrust::device_vector<float> > v;
v.reserve(2);
float test;
float* tmp;
//Initialize first vector on GPU 0
cudaSetDevice( 0 );
v.emplace_back( 65536, 1.0f );
tmp = thrust::raw_pointer_cast( v.at(0).data() );
std::cout << " Host TALK: Raw pointer of vector 0 at step 0 " << (void*)tmp << std::endl;
//Try to use it raw pointer
write_memory<<<1,1,0,0>>>( tmp, 2.0f );
checkCudaErrors( cudaStreamSynchronize( NULL ) );
test = v.at(0)[0];
std::cout << " Host TALK: After first kernel launch, value is " << test << std::endl;
//Initialize second vector on GPU 1, but we do not use it
cudaSetDevice( 1 );
v.emplace_back( 65536, 1.0f );
std::cout << " Host TALK: Raw pointer of vector 0 at step 1 is now " << (void*)thrust::raw_pointer_cast( v.at(0).data() ) << " != " << (void*)tmp << std::endl;
std::cout << " Host TALK: Raw pointer of vector 1 at step 1 is " << (void*)thrust::raw_pointer_cast( v.at(1).data() ) << std::endl;
//Try to use the first vector : No segmentation fault ?
cudaSetDevice( 0 );
test = v.at(0)[0];
std::cout << " Host TALK: Before second kernel launch, value is " << test << std::endl;
write_memory<<<1,1,0,0>>>( thrust::raw_pointer_cast( v.at(0).data() ), 3.0f );
checkCudaErrors( cudaStreamSynchronize( NULL ) );
test = v.at(0)[0];
std::cout << " Host TALK: After second kernel launch, value is " << test << std::endl;
//Raw pointer stored elsewhere: generates a segmentation fault
write_memory<<<1,1,0,0>>>( tmp, 4.0f );
checkCudaErrors( cudaStreamSynchronize( NULL ) );
test = v.at(0)[0];
std::cout << " Host TALK: After third kernel launch, value is " << test << std::endl;
return 0;
}
这是我代码中最后一个地方,为了简单起见,我没有使用指向对象的指针 vector 而不是对象 vector ,但我发现我应该避免这些烦人的移动/复制问题......
现在的输出是:
主机对话:第 0 步 vector 0 的原始指针 0xb043c0000
GPU 对话:原始指针是 0xb043c0000
Host TALK:第一次内核启动后,值为 2
主机对话:第 1 步 vector 0 的原始指针现在是 0xb043c0000 != xb043c0000
主机对话:第 1 步 vector 1 的原始指针是 0xb07fc0000
Host TALK:在第二次内核启动之前,值为 2
GPU 对话:原始指针是 0xb043c0000
Host TALK:第二次内核启动后,值为 3
GPU 对话:原始指针是 0xb043c0000
Host TALK:第三次内核启动后,值为 4
最佳答案
所以我快速安装了 CUDA 来检验我的假设:添加 reserve
语句可以保留地址。
//declare a vector of vector
std::vector<thrust::device_vector<float> > v;
v.reserve(2); // <<-- HERE
float test;
float* tmp;
以及输出,首先是没有补丁。
$ nvcc thrust.cu -std=c++11 -o test
$ ./test
Host TALK: Raw pointer of vector 0 at step 0 0x700ca0000
GPU TALK: Raw pointer is 0x700ca0000
Host TALK: After first kernel launch, value is 2
Host TALK: Raw pointer of vector 0 at step 1 is now 0x700d20000 != 0x700ca0000
Host TALK: Raw pointer of vector 1 at step 1 is 0x700ce0000
Host TALK: Before second kernel launch, value is 2
GPU TALK: Raw pointer is 0x700d20000
Host TALK: After second kernel launch, value is 3
GPU TALK: Raw pointer is 0x700ca0000
Host TALK: After third kernel launch, value is 3
补丁:
$ nvcc thrust.cu -std=c++11 -o test
$ ./test
Host TALK: Raw pointer of vector 0 at step 0 0x700ca0000
GPU TALK: Raw pointer is 0x700ca0000
Host TALK: After first kernel launch, value is 2
Host TALK: Raw pointer of vector 0 at step 1 is now 0x700ca0000 != 0x700ca0000
Host TALK: Raw pointer of vector 1 at step 1 is 0x700ce0000
Host TALK: Before second kernel launch, value is 2
GPU TALK: Raw pointer is 0x700ca0000
Host TALK: After second kernel launch, value is 3
GPU TALK: Raw pointer is 0x700ca0000
Host TALK: After third kernel launch, value is 4
关于c++ - thrust::raw_pointer_cast 和多个 GPU,奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30500183/
谁能解释或指出在多 GPU/多显示器设置中渲染如何工作的解释(或至少一些线索)? 例如,我安装了 5 个 NVIDIA Quadro 4000 视频卡并连接了 9 个显示器。显示不进行任何分组。刚刚在
以下代码报错: import spacy spacy.require_gpu() Traceback (most recent call last): File "/home/user/Pycha
正如问题已经暗示的那样,我是深度学习的新手。我知道模型的学习过程在没有 GPU 的情况下会很慢。如果我愿意等待,如果我只使用CPU可以吗? 最佳答案 在计算深度学习(以及一般的神经网络)中执行的许多操
我知道 Renderscript 的设计是为了掩盖我正在运行的处理器的事实,但是有没有办法编写代码,以便在支持 GPU 计算的设备(目前是 Nexus 10)上运行显卡?有什么方法可以判断脚本的功能正
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 8 年前。 Improv
我想以编程方式找出可用的 GPU 及其当前内存使用情况,并根据内存可用性使用其中一个 GPU。我想在 PyTorch 中执行此操作。 我在这个 post 中看到了以下解决方案: import torc
我喜欢 GPU Gems 的结构化技术摘要。但是自上次发布以来已经过去了很长时间,应该开发新算法来处理新型硬件。 我可以阅读有关最近 GPU 技术成就的哪些信息? 潜伏在编程板上是唯一的方法吗? 最佳
我一直在做一些关于测量数据传输延迟的实验 CPU->GPU 和 GPU->CPU。我发现对于特定消息大小,CPU->GPU 数据传输速率几乎是 GPU->CPU 传输速率的两倍。谁能解释我为什么会这样
当我使用选项 --gres=gpu:1 向具有两个 GPU 的节点提交 SLURM 作业时,如何获取为该作业分配的 GPU ID?是否有用于此目的的环境变量?我使用的 GPU 都是 nvidia GP
我用 gpu、cuda 7.0 和 cudnn 6.5 安装了 tensorflow。当我导入 tensorflow 时,它运行良好。 我正在尝试在 Tensorflow 上运行一个简单的矩阵乘法,但
我们正在寻找有关 slurm salloc gpu 分配的一些建议。目前,给定: % salloc -n 4 -c 2 -gres=gpu:1 % srun env | grep CUDA CUD
我是否必须自定义为非 GPU Tensorflow 库编写的代码以适应tensorflow-gpu 库? 我有一个 GPU,想运行仅为非 GPU tensorflow 库编写的 Python 代码。我
我是否必须自定义为非 GPU Tensorflow 库编写的代码以适应tensorflow-gpu 库? 我有一个 GPU,想运行仅为非 GPU tensorflow 库编写的 Python 代码。我
我正在使用 pytorch 框架训练网络。我的电脑里有 K40 GPU。上周,我在同一台计算机上添加了 1080。 在我的第一个实验中,我在两个 GPU 上观察到相同的结果。然后,我在两个 GPU 上
有没有办法在 Slurm 上超额订阅 GPU,即运行共享一个 GPU 的多个作业/作业步骤?我们只找到了超额订阅 CPU 和内存的方法,但没有找到 GPU。 我们希望在同一 GPU 上并行运行多个作业
我可以访问 4 个 GPU(不是 root 用户)。其中一个 GPU(2 号)表现怪异,它们的一些内存被阻塞但功耗和温度非常低(好像没有任何东西在上面运行)。请参阅下图中 nvidia-smi 的详细
我正在尝试通过 Tensorflow 运行示例 seq2seq,但它不会使用 GPU。以下是我在带有 Tesla K20x 的 Linux 系统上安装 Tensorflow 所采取的步骤 git cl
一位电气工程师最近提醒我不要使用 GPU 进行科学计算(例如,在精度非常重要的地方),因为没有像 CPU 那样的硬件保护措施。这是真的吗?如果是的话,典型硬件中的问题有多普遍/严重? 最佳答案 实际上
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
最近我研究了强化学习,有一个问题困扰着我,我找不到答案:如何使用 GPU 有效地完成训练?据我所知,需要与环境持续交互,这对我来说似乎是一个巨大的瓶颈,因为这项任务通常是非数学的/不可并行化的。然而,
我是一名优秀的程序员,十分优秀!