好吧,很抱歉,如果这与之前看到的类似。 我有以下代码:
//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语言中的语法还是在我对如何实现此构想的全部理解上。
答案 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