Search code examples
cudanvccicc

Calling a function in an external C file from a cuda file


I have a C code (io.c) which compiles and runs perfectly. I am trying to call a function of the C code (io.c) from a cuda file (PCA.cu):

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
} 

I am using the following Makefile to compile and link io.c and 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

And I get segmentation fault (core dumped) when I run the generated executable (./PCA)

Any help?


Solution

  • I get segmentation fault (core dumped) when I run the generated executable (./PCA)

    This program expects a filename to be specified on the command line.

    If you run your program as-is the way you have described in your question (./PCA) it will seg fault.

    This has nothing to do with CUDA. The seg fault is arising because of this call:

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

    The argv[1] is expecting to pull a command line argument as the file name to be used in io.c here:

    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){
    

    If the first parameter (filename_header, which is argv[1] in main) is null (because you haven't specified the file name on the command line), the call to strstr will seg fault.

    Again, this is just a coding/usage error, and it has nothing to do with CUDA.

    The fix is to specify a filename on the command line (./PCA myfile), and even better write some code that detects when the user has not provided a valid filename and halt the program with an error message.