Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CUDA:在内核执行时从主机修改映射内存_C_Windows_Cuda - Fatal编程技术网

CUDA:在内核执行时从主机修改映射内存

CUDA:在内核执行时从主机修改映射内存,c,windows,cuda,C,Windows,Cuda,我想在内核执行时修改主机上的一段映射内存,然后从内核中读取该值 我试着用下面的方法来做。我有这样一个内核: __global__ void kernel(int* d_ptr) { *d_ptr = 1; while( *d_ptr); } bool kernel_running = 0; __global__ void kernel(int* d_ptr) { *d_ptr = 1; while( *d_ptr) printf("%d\n", *d_ptr)

我想在内核执行时修改主机上的一段映射内存,然后从内核中读取该值

我试着用下面的方法来做。我有这样一个内核:

__global__ void kernel(int* d_ptr)
{
    *d_ptr = 1;
    while( *d_ptr);
}
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;
}
d_ptr映射到可从主机访问的内存块

我还有一个像这样的主机线程

void run( void* input )
{
    int* h_ptr = (int*)input;
    while( kernel_running)
        *h_ptr = 0;
}
__global__ void kernel(int* d_ptr)
{
    *d_ptr = 1;
    while( *d_ptr) printf("%d\n", *d_ptr);
}
因此,主机线程正在将0反复写入内核反复读取的位置,直到看到0为止。理论上,内核应该在读取主机线程写入的值后立即停止。问题是内核从未读取此0,因此它从未终止

奇怪的是,如果我像这样在内核中添加print语句

void run( void* input )
{
    int* h_ptr = (int*)input;
    while( kernel_running)
        *h_ptr = 0;
}
__global__ void kernel(int* d_ptr)
{
    *d_ptr = 1;
    while( *d_ptr) printf("%d\n", *d_ptr);
}
然后它读取0并终止。我不知道发生了什么事。没有提供关于并发访问映射内存的太多信息,也很难找到解决这个问题的方法。有什么建议吗?我用的是Windows,我用的是编译

nvcc -g -arch=sm_20 -lineinfo
整个代码如下所示:

__global__ void kernel(int* d_ptr)
{
    *d_ptr = 1;
    while( *d_ptr);
}
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;
}
bool内核运行=0;
__全局无效内核(int*d\u ptr)
{
*d_ptr=1;
而(*d_ptr)printf(“%d\n”,*d_ptr);
}
无效运行(无效*输入)
{
int*h_ptr=(int*)输入;
while(内核运行时)
{
*h_ptr=0;
}
}
int main()
{
//主机和设备指针
int*h_ptr=0;
int*d_ptr=0;
//初始化指针
断言(cudaHostAlloc(&h_ptr,sizeof(int),cudahostallocmap)=cudaSuccess);
断言(cudaHostGetDevicePointer(&d_ptr,h_ptr,0)=cudaSuccess);
//运行内核
内核运行=1;
_beginthread(run,0,h_ptr);
内核(d_ptr);
断言(cudaDeviceSynchronize()==cudaSuccess);
内核运行=0;
}
建议:

  • 在调用
    cudaHostAlloc
    之前添加此项:

    cudaSetDeviceFlags(cudaDeviceMapHost);
    
    报告提出了这一点

  • 将您的标志变量声明为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;
}
#包括
#定义cudaCheckErrors(msg)\
做{\
cudaError\u t\u err=cudaGetLastError()\
如果(_err!=cudaSuccess){\
fprintf(标准,“致命错误:%s(%s位于%s:%d)\n”\
msg,cudaGetErrorString(_err)\
__文件(行)\
fprintf(stderr,“***失败-中止\n”)\
出口(1)\
} \
}而(0)
__全局无效mykernel(volatile int*数据){
而(*数据){};
printf(“完成的”\n);
}
int main(){
int*d_数据,*h_数据;
cudaSetDeviceFlags(cudaDeviceMapHost);
cudaCheckErrors(“cudaSetDeviceFlags错误”);
cudaHostAlloc((void**)和h_数据,sizeof(int),cudaHostAllocMapped);
cudaCheckErrors(“cudaHostAlloc错误”);
cudaHostGetDevicePointer(&d_数据,h_数据,0);
cudaCheckErrors(“cudaHostGetDevicePointer错误”);
*h_数据=1;
printf(“内核启动\n”);
mykernel(d_数据);
cudaCheckErrors(“内核失败”);
getchar();
*h_数据=0;
cudaDeviceSynchronize();
cudaCheckErrors(“内核故障2”);
返回0;
}

谢谢你的回答!我试过你的代码,但是我的内核中*data的值在启动时是0,所以我没有复制1,因为某种原因…好的,我发现我在前面的评论中提到的问题是因为,因为我在Windows中使用WDDM驱动程序,内核直到cudaDeviceSynchronize()才启动,*h_data是零,这就是为什么我从内核直接读取零。。。我通过在内核调用之后立即触发早期启动来解决这个问题,如下所述: