CUDA C指针提供令人困惑的值

时间:2018-06-20 22:16:58

标签: c cuda

好吧,很抱歉,如果这与之前看到的类似。 我有以下代码:

//kern.cu
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>
extern "C"{
#include "Kernalize.h"
#include <stdio.h>
}

extern "C" {
    __device__ void *dat;
    __global__ void memManageDevice(void *data){
        dat=data;
    }
    void memManageD(void *data){
        printf("A%d",data);
        void *d;
        printf("B%d",d);
        cudaMemcpy(d,&data,sizeof(data),cudaMemcpyHostToDevice);
        memManageDevice<<<1,1>>>(data);
    }
    __global__ void MemManageC(void *r){//don't call this unless in this file.
        r=dat;
    }
    void* memManageH(void *s){
        printf("C%d",s);
        void *dr;
        cudaMalloc((void **)&dr, sizeof(s));
        void *hr;
        int size=sizeof(s);
        MemManageC<<<1,1>>>(dr);
        cudaMemcpy(&hr, dr, size, cudaMemcpyDeviceToHost);
        printf("D%d",hr);
        return hr;
    }
    __global__ void kernalize(void (*ptr)(void *)) {
        (*ptr)(dat);
    }
    void Start(int d1, int d2, void (*ptr)(void *), void *data) {//TODO: make arrays as to start many  kernels
        int size=sizeof(data);
        // void *ddata;
        // bool ab=true;
        // bool *coolbeans=&ab;
        // memManageD<<<1,1>>>(data);
        kernalize<<<d1,d2,d2*size>>>(ptr);
        // data=sdata;
        // coolbeans=false;
        //kernalize(ptr,data);
    }
}

然后将其编译为.so:

nvcc --ptxas-options=-v --compiler-options '-fPIC' -o libpar.so --shared kern.cu

然后从普通C语言中引用它:

typedef void (*gFunc) ();
typedef void (*sFunc) (int,int,gFunc*,void *data);

typedef void* (*hFunc) (void *);
typedef void (*dFunc) (void *);
void toBe(void *data){
        data=12;
        while(1){}//side-expirement, don't think it's the stem of the issue.
}
int main() {
    printf("start");
    sFunc fS;
    hFunc hS;
    dFunc dS;
    void* hLibrary = dlopen("./libpar.so", RTLD_NOW | RTLD_GLOBAL);
    if(hLibrary == NULL) {
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }
    int i=42;
    *(void**)(&dS)=dlsym(hLibrary,"memManageD");
    (void) dS(i);
    sleep(1);
    printf("checkpoint");
    *(void**)(&fS)=dlsym(hLibrary,"Start");
    (void) fS(2,2,toBe,&i);
    sleep(1);
    *(void**)(&hS)=dlsym(hLibrary,"memManageH");
    int x=(void*) hS(&i);
    printf("%d", x);

    return 0;
}

您也许可以通过我那令人毛骨悚然的代码来分辨,将toBe函数传递给CUDA C内核,该内核在执行时将把非类型变量指针“ data”更改为12。“ data”是正常c中对“ i”的引用,从42开始。不幸的是,我的输出是1,而不是12:

 startA42B431891052checkpointC-288453328D1

实际上只是“ A42”和“ D1”之间的垃圾清单。 我对CUDA C和C还是比较陌生。 (我将大部分时间都花在高级编程语言上。) 因此,问题实际上是我在犯一个愚蠢的错误,无论是在我对CUDA的理解,我在C语言中的语法还是在我对如何实现此构想的全部理解上。

1 个答案:

答案 0 :(得分:0)

这是我为什么会看到输出的理解:

  • A42可以正常工作,因为我等于42

  • B431891052,因为指针void* d未初始化,并且可能包含垃圾值,并且打印语句printf("B%d",d)仅打印其低32位。 / p>

  • C-288453328,因为语句printf("C%d",s)打印变量i的低32位。在32位中,数字-288453328对应于十六进制数字0xEECE8D30;我认为这是堆栈地址0x7FFFEECE8D30的低32位。

  • D1,因为hr将包含dr所指向的前8个字节。它尚未初始化,在此示例中,它指向的值恰好是1。

我认为分配D12的功能memManageC可能需要更改为以下内容:

__global__ void MemManageC(int *r) {
    *r = dat;
}

因此,r所指向的内容将具有dat的值。在没有取消引用的情况下,该函数仅修改传入的参数,这是一个空操作,可能会被编译器优化。

拥有D12还需要toBe来正确设置dat的值,这似乎需要更多代码更改。 toBe是主机端函数,可以在此答案中找到__global__或__kernel__函数中主机端函数的用法:Passing Host Function as a function pointer in __global__ OR __device__ function in CUDA