2015-07-25 3 views
1

Я пытался запустить простую программу CUDA, которая выполняет добавление матрицы по определенному размеру.undefined ссылка на функцию C++, создаваемую промежуточным объектным файлом

Вот мой код:

main.cpp

/* sample CUDA programming to prove that (AB)transpose=(B)transpose*(A)transpose */ 

#include "common.h" 
#include "utils.h" 
#include <iostream> 
#include <stdlib.h> 
#include <time.h> 


using namespace std; 


void preprocess(int *A, int *B, int *C, int **da, int **db, int **dc,int M, int N, int P,int blksize); 
void checktransposeppt(int *da, int *db, int *dc); 

void display(int a[], int b[]) 
{ 
    //display the matrices 
} 

int main() 
{ 

    int A[M*P],B[P*N]; 
    int C[M*N]; 

    int *da; 
    int *db; 
    int *dc; 


    //initializing values for A and B 

    display(A,B); 

    preprocess(A,B,C,&da,&db,&dc,M,N,P,blksize); 

    checktransposeppt(da,db,dc); 

    checkCudaErrors(cudaFree(da)); 
    checkCudaErrors(cudaFree(db)); 
    checkCudaErrors(cudaFree(dc)); 

} 

и вот preprocess.cpp: - в основном делает cudamalloc, cudamemcpy hosttodevice массивов и devicetohost результирующего

#include "utils.h" 

void preprocess(int *h_a, int *h_b, int *h_c,int **d_a,int **d_b,int **d_c,int M, int N, int P, int blksize) 
{ 

    checkCudaErrors(cudaFree(0)); 
    checkCudaErrors(cudaMalloc(d_a,(size_t)sizeof(int)*(M*P))); 
    checkCudaErrors(cudaMalloc(d_b,(size_t)sizeof(int)*(P*N))); 
    checkCudaErrors(cudaMalloc(d_c,(size_t)sizeof(int)*(M*N))); 
    checkCudaErrors(cudaMemset(d_c,0,(size_t)sizeof(int)*(M*N))); 

    checkCudaErrors(cudaMemcpy(*d_a,h_a,(size_t)sizeof(int)*(M*P),cudaMemcpyHostToDevice)); 
    checkCudaErrors(cudaMemcpy(*d_b,h_b,(size_t)sizeof(int)*(P*N),cudaMemcpyHostToDevice)); 
    checkCudaErrors(cudaMemcpy(h_c,*d_c,(size_t)sizeof(int)*(M*N),cudaMemcpyDeviceToHost)); 
} 

и это common.h, центральное место для определения большинства внешних заголовков и глобальных переменных

#ifndef COMMON_H 
#include <cuda.h> 
#include <cuda_runtime.h> 

#define COMMON_H 

extern int M=256; 
extern int P=128; 
extern int N=64; 
extern int blksize=16; 

extern dim3 gridsize(M/blksize,N/blksize,1); 
extern dim3 blocksize(blksize,blksize,1); 

#endif 

kernel.cu

#include "utils.h" 
#include "common.h" 

__global__ void abkerneltranspose(int *d_a,int *d_b,int *d_c,int N); 


    __global__ 
void abkerneltranspose(int *d_a,int *d_b,int *d_c,int N) 
{ 
    int blkx=blockIdx.x; 
    int blky=blockIdx.y; 
    int thdx=threadIdx.x; 
    int thdy=threadIdx.y; 

    int row=blkx*blockDim.x+threadIdx.x; 
    int col=blky*blockDim.y+threadIdx.y; 

    d_c[row*N+col]=d_a[row*N+col]+d_b[row*N+col]; 

} 

void checktransposeppt(int *d_a,int *d_b,int *d_c) 
{ 

    dim3 gridsize(M/blksize,N/blksize,1); 
    dim3 blocksize(blksize,blksize,1); 

    abkerneltranspose<<<gridsize,blocksize>>>(d_a,d_b,d_c,N); 
} 

и вот где я подозреваю, что преступник будет: Makefile

NVCC=nvcc 
NVCC_OPTS=-O3 -arch=sm_20 -Xcompiler -Wall -Xcompiler -Wextra -m64 

all: app 

app: gpucompile.o cpucompile.o Makefile 
    nvcc -o app gpucompile.o cpucompile.o -L $(NVCC_OPTS) $(GCC_OPTS) 

gpucompile.o: kernel.cu 
    nvcc -c kernel.cu $(NVCC_OPTS) 

cpucompile.o: main.cpp preprocess.cpp 
    nvcc -x cu main.cpp preprocess.cpp -I. -I $(GCC_OPTS) -I $(CUDA_INCLUDEPATH) 

clean: 
    rm -f *.o hw *.bin 

нормально здесь проблема

по команде макияжем, Компилируется но генерирует ошибку

/tmp/tmpxft_00002074_00000000-21_main.o: In function main': tmpxft_00002074_00000000-3_main.cudafe1.cpp:(.text+0x543): undefined reference to checkTransposeppt(int*, int*, int*)'

Я действительно не знаю, почему это происходит. Я компилирую и создаю код cpp отдельно (просто игнорируйте -x cu, он не вызывает ошибки) и выполните то же самое kernel.cu, которое я позже свяжу.

Но эта ошибка выбрасывается промежуточным main.o, что заставляет меня думать, что ему не удалось создать cpucompile.o. Но не смог ли компоновщик подождать, пока он не получит gpucompile.o, а затем свяжет два.

Кроме того, я попытался создать отдельные объектные файлы main.o, preprocess.o и kernel.o и связать их все в одном шаге

тогда я получаю следующую дополнительную ошибку:

/tmp/tmpxft_00002f88_00000000-16_main.o: In function main': tmpxft_00002f88_00000000-3_main.cudafe1.cpp:(.text+0x532): undefined reference to preprocess(int*, int*, int*, int**, int**, int**, int, int, int, int)'

я пропустил что-то основное, может кто-нибудь объяснить, что здесь происходит?

Также, что лучше всего подходит для выполнения такого проекта: Я имею в виду, что я разделяю код компилятора и код процессора, а затем связываю их. У меня также есть общий заголовок, где я определяю внешние заголовки и определения глобальных переменных/классов/функций. Какие-либо предложения?

ответ

2

Да, ваш файл подписи неправильный.

Цель приложения, которую вы хотите построить, - app, а цель makefile для нее настраивается, возможно, работоспособным способом.

Для цели app требуется gpucompile.o и cpucompile.o объектов.

Вы указали цель для каждого требуемого объекта.

Цель gpucompile.o установлена, возможно, в работоспособном режиме.По-прежнему существует проблема в том, что по умолчанию создается kernel.o, а не gpucompile.o

Цель cpucompile.o не работает. Он разбит несколькими способами. Во-первых, он, похоже, скопирован из цели makefile, которая включает фазу связи, но это не то, что мы хотим - вы создаете несвязанный объект (cpucompile.o) на этом этапе. Кроме того, мы обычно не создаем два отдельных несвязанных объекта (main.o и preprocess.o) в один несвязанный объект.

В общем, я бы рекомендовал переключиться на формат файла makefile, который просто обрабатывает файлы .cu и .cpp-файлы аналогичным образом - создайте цель для каждого и создайте каждый объект. Затем соедините все объекты вместе, чтобы создать исполняемый файл. Нет необходимости пытаться создать отдельный «объект gpu», который включает в себя весь код GPU, и отдельный «объект cpu», который включает весь код ЦП, а затем связывает их вместе.

У вас есть отдельная проблема в коде, где вы определяете M и другие переменные в common.h, а затем включаете это в несколько файлов. Это приведет к ошибке с множественным определением. Есть несколько способов исправить это. Один из возможных подходов заключаются в изменении файла commons.h как это:

#ifndef COMMON_H 
#include <cuda.h> 
#include <cuda_runtime.h> 

#define COMMON_H 

extern int M; 
extern int P; 
extern int N; 
extern int blksize; 

extern dim3 gridsize; 
extern dim3 blocksize; 

#endif 

затем добавьте следующие инициализации к началу одного ваших файлов, такие как main.cpp:

int M=256; 
int P=128; 
int N=64; 
int blksize=16; 

dim3 gridsize(M/blksize,N/blksize,1); 
dim3 blocksize(blksize,blksize,1); 

с учетом этих изменений, а также с помощью Makefile так:

NVCC=nvcc -O3 -arch=sm_20 -Xcompiler -Wall -Xcompiler -Wextra -m64 

all: app 

app: kernel.o main.o preprocess.o Makefile 
     $(NVCC) -o app kernel.o main.o preprocess.o 

kernel.o: kernel.cu 
     $(NVCC) -c kernel.cu 

main.o: main.cpp 
     $(NVCC) -x cu -c main.cpp 

preprocess.o: preprocess.cpp 
     $(NVCC) -x cu -c preprocess.cpp 
clean: 
     rm -f *.o app 

я смог построить свой код со следующими оговорками:

  1. Вы не предоставили utils.h Итак, я создал один.
  2. Есть все еще различные предупреждения компиляции/ссылки. Это связано с вашим кодом, а не с созданием файла makefile.
Смежные вопросы