CUDA 内核可以修改主机内存吗?

Can CUDA Kernels Modify Host Memory?

有没有办法通过将指向该整数的指针传递给内核来让内核修改该整数?指针似乎指向设备内存中的地址,因此内核不会影响主机。

这是我注意到的行为的简化示例。

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <iostream>

__global__
void change_cuda(int* c);

void change_var(int* c);

int main() {
    using namespace std; 

    int c = 0;
    int* ptc = &c;

    change_var(ptc); // *ptc = 123

    cout << c << endl;

    cudaError_t errors;

    cudaMallocManaged((void**)&ptc, sizeof(int));

    change_cuda<<<1, 1>>> (ptc); // *ptc = 555

    errors = cudaDeviceSynchronize();

    cudaFree(ptc);

    cout << cudaGetErrorString(errors) << endl;
    cout << c << endl;

    return 0;
}

__global__
void change_cuda(int* c) {
    *c = 555;
}

void change_var(int* c) {
    *c = 123;
}

理想情况下,这会将 c 修改为最后的 555,但此示例的输出是

123
no error
123

显然我误解了它的工作原理。获得我期望的行为的正确方法是什么?

是的,你误会了。 cudaMallocManaged 是一个 分配器 ,例如 mallocnew。它 returns 一个指向请求大小的 新分配 的指针。

允许从设备代码访问基于主机堆栈的变量不是某种方法。

但是,cudaMallocManaged返回的指针指向的分配区域可以从设备代码或主机代码访问。 (它不会指向您的 c 变量。)

您可以通过进行以下更改来最低限度地修复您的代码。 1. 注释掉对cudaFree的调用。 2. 打印出 *ptc 而不是 c 的值。也许更明智的改变可能是这样的:

int main() {
    using namespace std; 

    int* ptc;

    cudaMallocManaged((void**)&ptc, sizeof(int));

    change_var(ptc); // *ptc = 123

    cout << *ptc << endl;

    cudaError_t errors;

    change_cuda<<<1, 1>>> (ptc); // *ptc = 555

    cudaDeviceSynchronize();

    errors = cudaGetLastError();

    cout << cudaGetErrorString(errors) << endl;
    cout << *ptc << endl;

    return 0;
}