我想从内核正在执行的主机上修改一段映射内存,然后从内核中读取该值。
我正在尝试以下方式执行此操作。我有这样的内核:
__global__ void kernel(int* d_ptr)
{
*d_ptr = 1;
while( *d_ptr);
}
d_ptr映射到可从主机访问的内存。
我也有一个看起来像这样的主机线程
void run( void* input )
{
int* h_ptr = (int*)input;
while( kernel_running)
*h_ptr = 0;
}
因此,主机线程重复地将0写入内核重复读取的位置,直到它看到0.理论上,内核应该在读取主机线程写入的值后立即停止。问题是内核永远不会读取此0,因此它永远不会终止。
奇怪的是,如果我在内核中添加一个print语句,就像这样
__global__ void kernel(int* d_ptr)
{
*d_ptr = 1;
while( *d_ptr) printf("%d\n", *d_ptr);
}
然后它会读取0并终止。我不知道发生了什么。 cuda programming guide没有提供有关对映射内存的并发访问的大量信息,并且很难找到解决此问题的问题。有什么指针吗?我正在使用Windows,而我正在使用
进行编译nvcc -g -arch=sm_20 -lineinfo
整个代码如下所示:
bool kernel_running = 0;
__global__ void kernel(int* d_ptr)
{
*d_ptr = 1;
while( *d_ptr) printf("%d\n", *d_ptr);
}
void run( void* input )
{
int* h_ptr = (int*)input;
while( kernel_running)
{
*h_ptr = 0;
}
}
int main()
{
// HOST AND DEVICE POINTERS
int* h_ptr = 0;
int* d_ptr = 0;
// INITIALIZE POINTERS
assert( cudaHostAlloc(&h_ptr, sizeof(int), cudaHostAllocMapped) == cudaSuccess);
assert( cudaHostGetDevicePointer(&d_ptr, h_ptr, 0) == cudaSuccess);
// RUN KERNEL
kernel_running = 1;
_beginthread( run, 0, h_ptr);
kernel<<<1,1>>>(d_ptr);
assert( cudaDeviceSynchronize() == cudaSuccess);
kernel_running = 0;
}
答案 0 :(得分:0)
建议:
在致电cudaHostAlloc
之前添加此内容:
cudaSetDeviceFlags(cudaDeviceMapHost);
documentation暗示了这一点。
将您的标志变量声明为volatile
:
__global__ void kernel(volatile int* d_ptr)
以下代码适用于我而不使用线程:
#include <stdio.h>
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
__global__ void mykernel(volatile int *data){
while (*data) {};
printf("finished\n");
}
int main(){
int *d_data, *h_data;
cudaSetDeviceFlags(cudaDeviceMapHost);
cudaCheckErrors("cudaSetDeviceFlags error");
cudaHostAlloc((void **)&h_data, sizeof(int), cudaHostAllocMapped);
cudaCheckErrors("cudaHostAlloc error");
cudaHostGetDevicePointer(&d_data, h_data, 0);
cudaCheckErrors("cudaHostGetDevicePointer error");
*h_data = 1;
printf("kernel starting\n");
mykernel<<<1,1>>>(d_data);
cudaCheckErrors("kernel fail");
getchar();
*h_data = 0;
cudaDeviceSynchronize();
cudaCheckErrors("kernel fail 2");
return 0;
}