从 cuda 文件调用外部 C 文件中的函数

Posted

技术标签:

【中文标题】从 cuda 文件调用外部 C 文件中的函数【英文标题】:Calling a function in an external C file from a cuda file 【发布时间】:2014-10-24 11:34:39 【问题描述】:

我有一个可以完美编译和运行的 C 代码 (io.c)。我正在尝试从 cuda 文件 (PCA.cu) 调用 C 代码 (io.c) 的函数:

io.c

 #include <stdio.h>
#include <stdlib.h>
void Read_header(char filename_header[200], int *num_lines, int *num_samples, int *num_bands, int *lines_samples, int *data_type)

    FILE *fp;
    char line[200];
       char *ptr;
        int i=0;


    if(strstr(filename_header, ".hdr")==NULL)
        exit(1);
    

    if ((fp=fopen(filename_header,"r"))==NULL)
        exit(1);
    
    else
        fseek(fp,0L,SEEK_SET);

        while(fgets(line, 200, fp)!='\0')
            if(strstr(line, "samples")!=NULL)
                ptr=strrchr(line, ' ');
                ptr= ptr+1;
                *num_samples=atoi(ptr);
            
            if(strstr(line, "lines")!=NULL)
                ptr=strrchr(line, ' ');
                ptr= ptr+1;
                *num_lines=atoi(ptr);
            
            if(strstr(line, "bands")!=NULL)
                ptr=strrchr(line, ' ');
                ptr= ptr+1;
                *num_bands=atoi(ptr);
            
            if(strstr(line, "data type")!=NULL)
                ptr=strrchr(line, ' ');
                ptr= ptr+1;
                *data_type=atoi(ptr);
            


        //while
        (*lines_samples)=(*num_lines)*(*num_samples);   

        fclose(fp);
    //else 

PCA.cu

#include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
#include <math.h>
#include <sys/time.h>


/*C includes*/

extern "C"


#include "io.h"




#include "cuda.h"

/* Main */
int main(int argc, char** argv)

    int num_lines, num_samples, num_bands, lines_samples, data_type;
    Read_header(argv[1], &num_lines, &num_samples, &num_bands, &lines_samples, &data_type);
    printf("lines = %d\nsamples = %d\nbands = %d\npixels = %d\ndata_type = %d\n", num_lines, num_samples, num_bands, lines_samples, data_type);
        // the rest of source code has been removed for simplicity
 

我正在使用以下 Makefile 来编译和链接 io.c 和 PCA.cu:

MKL =1

CUDA_PATH=/usr/local/cuda-6.0
BUILD_DIR=./build

CUDA_INCLUDE_DIR=-I. -I$(CUDA_PATH)/include
CUDA_LIB_DIR=-L$(CUDA_PATH)/lib64

CUDALIBS=-lcublas -lcudart
utilS= -lpthread -lm

CFLAGS= -Wwrite-strings

CUDAFLAGS= --gpu-architecture sm_20

io.o : io.c
icc $(CFLAGS) -c -O3 io.c -o $(BUILD_DIR)/io.o

PCA.o: PCA.cu
nvcc $(CUDAFLAGS) $(CUDA_INCLUDE_DIR) -c -O3 PCA.cu -o $(BUILD_DIR)/PCA.o

#everything is already compiled, this is just a call to the linker
PCA: io.o PCA.o
icc $(CFLAGS) $(BUILD_DIR)/io.o $(BUILD_DIR)/PCA.o $(CUDA_LIB_DIR) $(utilS) $(CUDALIBS) -o PCA

当我运行生成的可执行文件 (./PCA) 时出现分段错误(核心转储)

有什么帮助吗?

【问题讨论】:

拜托,您能否发布其他人可以复制、粘贴、编译和运行在他身边的最小大小的代码? 我现在猜测这与从 CUDA 代码调用 C 代码时遇到的一个常见问题有关:nvcc 将 .cu 文件中的代码视为 C++ 代码,因此所有函数名都被修饰。为了从 .cu 文件中的宿主代码调用 .c 文件中定义的函数,该函数的可见原型必须声明为 extern "C" 以防止 CUDA 编译器修饰名称。 【参考方案1】:

运行生成的可执行文件 (./PCA) 时出现分段错误(核心转储)

这个程序需要在命令行中指定一个文件名。

如果您按照问题 (./PCA) 中描述的方式运行程序,则会出现段错误。

这与 CUDA 无关。 seg 错误是因为这个调用而产生的:

Read_header(argv[1], &num_lines, &num_samples, &num_bands, &lines_samples, &data_type);

argv[1] 期望在此处提取命令行参数作为要在 io.c 中使用的文件名:

void Read_header(char filename_header[200], int *num_lines, int *num_samples, int *num_bands, int *lines_samples, int *data_type)
    ...  
    if(strstr(filename_header, ".hdr")==NULL)

如果第一个参数(filename_header,即main 中的argv[1])为空(因为您没有在命令行中指定文件名),则对strstr 的调用将出现段错误。

再次重申,这只是一个编码/使用错误,与 CUDA 无关。

解决方法是在命令行上指定一个文件名 (./PCA myfile),甚至更好地编写一些代码来检测用户何时没有提供有效的文件名并停止程序并显示错误消息。

【讨论】:

以上是关于从 cuda 文件调用外部 C 文件中的函数的主要内容,如果未能解决你的问题,请参考以下文章

C语言中,其他文件可否调用文件中的static函数?

C语言外部函数与内部函数

C语言中有关外部函数调用的问题

从按钮单击事件直接调用存储在外部 JS 文件中的 JavaScript 函数

C语言中有关外部函数调用的问题

怎样在C#中调用DLL中的函数,最好有代码和详细说明