对中间对象文件

时间:2015-07-25 03:34:28

标签: c++ cuda linker makefile

我试图运行一个简单的CUDA程序,该程序在特定大小上执行矩阵添加。

这是我的代码:

的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

好的,这是问题

on make命令,它正确编译但抛出错误

  

/tmp/tmpxft_00002074_00000000-21_main.o:在函数main': tmpxft_00002074_00000000-3_main.cudafe1.cpp:(.text+0x543): undefined reference to中checkTransposeppt(int *,int *,int *)&#39;

我真的不确定为什么会这样。我分别编译和创建cpp代码(只是忽略-x cu,它不会导致错误)并执行相同的操作 我稍后链接的kernel.cu。

但是这个错误是由中间main.o抛出的,这让我相信它在创建cpucompile.o时失败了。但是链接器无法等到它获得gpucompile.o然后链接这两个链接。

此外,我尝试创建单独的目标文件main.o,preprocess.o和kernel.o并将它们全部链接一步

然后我收到以下额外错误:

  

/tmp/tmpxft_00002f88_00000000-16_main.o:在函数main': tmpxft_00002f88_00000000-3_main.cudafe1.cpp:(.text+0x532): undefined reference to preprocess(int *,int *,int *,int **,int **,int **,int,   int,int,int)&#39;

我错过了一些基本的东西,有人可以解释这里出了什么问题吗?

执行这样的项目的最佳做法是什么:我的意思是我将编译设备代码和cpu代码分开,然后将它们链接起来。我还有一个公共头,我在其中定义外部头和全局变量/类/函数定义。有什么建议吗?

1 个答案:

答案 0 :(得分:2)

是的,你的makefile不正确。

您要构建的应用程序目标是app,并且该makefile的目标设置可能是可行的。

app目标需要gpucompile.ocpucompile.o个对象。

您已为每个必需对象指定了目标。

gpucompile.o目标以可行的方式设置。还有一个问题是它默认创建kernel.o,而不是gpucompile.o

cpucompile.o目标无法使用。它在几个方面被打破。首先,它似乎是从包含链接阶段的makefile目标复制的,但这不是我们想要的 - 您此时正在创建一个未链接的对象(cpucompile.o)。此外,我们通常不会将两个单独的未链接对象(main.o和preprocess.o)构建到一个未链接的对象中。

一般情况下,我建议切换到一个makefile格式,它只是以类似的方式处理.cu文件和.cpp文件 - 为每个文件创建一个目标,并将每个文件构建到一个对象中。然后将所有对象链接在一起以创建可执行文件。没有必要尝试创建一个单独的&#34; gpu对象&#34;包括所有GPU代码,以及单独的&#34; cpu对象&#34;包括所有CPU代码,然后将它们链接在一起。

您的代码中有一个单独的问题,您在common.h中定义M和其他变量,然后将其包含在多个文件中。这将导致多重定义链接错误。有多种方法可以解决这个问题。一种可能的方法是修改你的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的构造。