CUDA映射内存:设备 - >主机写入在主机上不可见

时间:2015-10-31 18:58:21

标签: cuda

我试图做的是修改驻留在映射内存中的变量,该变量会导致主程序退出。

但是主程序在s3getfile /path/to/file | vsql -h host -U user -w password -c 'COPY mytable FROM STDIN' 行继续旋转,而不是这个。我不知道如何刷新新值,因此它也可以在主机端看到。

顺便说一下。该变量在任何地方都被声明为while (var == 0) ;,我尝试使用volatile函数但没有成功。

主持人 - >设备方向运作良好。

系统:Windows 7 x64,驱动程序358.50,GTX 560

以下是我无法使用的代码:

__threadfence_system()

1 个答案:

答案 0 :(得分:4)

当我在linux上运行你的代码时,它会按原样运行。

但是在Windows上,WDDM命令批处理存在问题。实际上,在您进入挂起的while循环之前,您的内核无法启动并且未启动。

WDDM命令队列是最终将发送到GPU设备的命令队列。各种事件将导致此队列被刷新"以"批次"对GPU的命令。

各种cuda运行时API调用可以有效地强制执行"刷新"命令队列的名称,例如cudaDeviceSynchronize()cudaMemcpy()。但是,在内核启动之后,您不会在进入while循环之前发出任何运行时API调用。结果,在这种情况下,似乎内核调用正在“卡住”#34;在队列中,从不"刷新"。

您可以通过多种方式解决此问题,例如,在启动内核后记录事件,然后查询该事件的状态。这将具有刷新队列的效果,这将启动内核。

以下是对我有用的代码示例修改:

#include <stdio.h>
static void handleCUDAError(cudaError_t err, const char *file, int line)
{
    if (err != cudaSuccess) {
        printf("%s in %s at line %d\n", cudaGetErrorString(err), file, line);
        exit(EXIT_FAILURE);
    }
}

#define CUDA_ERROR_CHECK(err) (handleCUDAError(err, __FILE__, __LINE__ ))

__global__ void echoKernel(volatile int* semaphore)
{
    *semaphore = 1;

    __threadfence_system();
}

int main()
{
    CUDA_ERROR_CHECK(cudaSetDevice(0));
    CUDA_ERROR_CHECK(cudaSetDeviceFlags(cudaDeviceMapHost));

    volatile int var = 0;
    volatile int *devptr;

    CUDA_ERROR_CHECK(cudaHostRegister((int*)&var, sizeof(int), cudaHostRegisterMapped));
    CUDA_ERROR_CHECK(cudaHostGetDevicePointer(&devptr, (int*)&var, 0));

    cudaEvent_t my_event;
    CUDA_ERROR_CHECK(cudaEventCreate(&my_event));

    echoKernel << < 1, 1 >> > (devptr);
    CUDA_ERROR_CHECK(cudaEventRecord(my_event));
    cudaEventQuery(my_event);

    while (var == 0);

    CUDA_ERROR_CHECK(cudaDeviceSynchronize());

    CUDA_ERROR_CHECK(cudaHostUnregister((int*)&var));
    CUDA_ERROR_CHECK(cudaDeviceReset());

    return 0;
}

在CUDA 7.5,驱动程序358.50,Win7 x64发布项目,GTX460M上进行了测试。

请注意,我们不会在标准错误检查程序中包含cudaEventQuery调用,因为它的预期行为是在事件尚未完成时返回非零状态。