【问题标题】:My simple CUDA wrapper and Makefile do not work我的简单 CUDA 包装器和 Makefile 不起作用
【发布时间】:2014-03-22 00:28:20
【问题描述】:

这是我在这里的第一篇文章 - 所以请耐心等待我。我目前正在尝试弄清楚如何编译一个包含普通 *.c 文件和一个 *.cu 文件的简单项目。显然,我想使用 nvcc 来做到这一点,我有两个“库”,它们基本上应该做同样的事情,但一个依赖于 OMP,另一个依赖于 CUDA。但是在浏览网页并通过 stackoverflow 爬行大约一天后,我完全被卡住了。这是我得到的:

我的来源/main.c:

#include <math.h>
#include <stdlib.h>
#include <stdio.h>

#include "../include/mylib_omp.h"
#include "../include/mylib_cuda.h"

int main(){

    myfunc_CUDA(3.0,4);

    return 0;
}

我的包含/mylib_omp.h:

#ifndef __MYLIB_OMP_H__
#define __MYLIB_OMP_H__

#include <omp.h>

void myfunc_OMP(float, int);

#endif

我的包含/mylib_cuda.h:

#ifndef __MYLIB_CUDA_H__
#define __MYLIB_CUDA_H__

#include <cuda_runtime_api.h>
#include <cuda.h>

void myfunc_CUDA(float, int);

#endif

我的来源/mylib_omp.c:

#ifndef __MYLIB_OMP_C__
#define __MYLIB_OMP_C__

#include "../include/mylib_omp.h"

void myfunc_OMP(float, int){
    int i;

    #pragma omp parallel
    {
        #pragma omp for
        for (i = 0; i < 1000; i++){
            int k = 0;
        }
    }
}

#endif

我的来源/mylib_cuda.cu

#ifndef __MYLIB_CUDA_CU__
#define __MYLIB_CUDA_CU__

extern "C"{
#include "../include/mylib_cuda.h"
}

extern "C"
void myfunc_CUDA(float a, int b){
    float* i;
    cudaMalloc((void **) &i,5*sizeof(float));
}

#endif

最后是我的 Makefile:

CC = nvcc
OUT = main

INCL_DIR = -I include
SOUR_DIR = sources

SOURCES =   ${SOUR_DIR}/main.c \
        ${SOUR_DIR}/mylib_omp.c \

CUDA_SOURCES =  ${SOUR_DIR}/mylib_cuda.cu 

H_FILES =   ${wildcard ${INCL_DIR}/*.h}

OBJECTS = ${SOURCES:.c=.o}
NVOBJECTS = ${CUDA_SOURCES:.cu=.o}

CFLAGS = -O3

NVCCFLAGS = -arch=sm_12 -ccbin=g++-4.4 -Xcompiler -openmp -x c++

LFLAGS = -lm -lcuda

INCLUDES = -I/opt/cuda/include
LIBS = -L/opt/cuda/lib64

${OUT}: ${OBJECTS} ${NVOBJECTS}
    $(CC) $(INCL_DIR) $(INCLUDES) $(LIBS) $(CFLAGS) $(LFLAGS) -o $@ $^ 

$(SOUR_DIR)/%.o : $(SOUR_DIR)/%.cu $(H_FILES)
    $(CC) $(NVCCFLAGS) $(INCL_DIR) $(INCLUDES) $(LIBS) -c -o $@ $<

$(SOUR_DIR)/%.o : $(SOUR_DIR)/%.c
    $(CC) $(NVCCFLAGS) $(INCL_DIR) $(INCLUDES) $(LIBS) -c -o $@ $<



clean :
    rm -f ${OBJECTS} ${NVOBJECTS} $(OUT)

很抱歉文件很多,但这基本上是尽可能短的。我昨天才弄清楚如何处理 makefile,因为我从未真正尝试过用任何语言处理更大的项目。所以现在解决问题。当我运行时,会发生以下情况:

[seb@seb-desktop make_cuda]$ make clean
rm -f sources/main.o sources/mylib_omp.o sources/mylib_cuda.o main
[seb@seb-desktop make_cuda]$ make
nvcc -arch=sm_12 -ccbin=g++-4.4 -Xcompiler -openmp -x c++ -I include -I/opt/cuda/include -L/opt/cuda/lib64 -c -o sources/main.o sources/main.c
nvcc -arch=sm_12 -ccbin=g++-4.4 -Xcompiler -openmp -x c++ -I include -I/opt/cuda/include -L/opt/cuda/lib64 -c -o sources/mylib_omp.o sources/mylib_omp.c
nvcc -arch=sm_12 -ccbin=g++-4.4 -Xcompiler -openmp -x c++ -I include -I/opt/cuda/include -L/opt/cuda/lib64 -c -o sources/mylib_cuda.o sources/mylib_cuda.cu
nvcc -I include -I/opt/cuda/include -L/opt/cuda/lib64 -O3 -lm -lcuda -o main sources/main.o sources/mylib_omp.o sources/mylib_cuda.o 
sources/main.o: In function `main':
main.c:(.text+0x12): undefined reference to `myfunc_CUDA(float, int)'
collect2: Fehler: ld gab 1 als Ende-Status zurück
Makefile:27: recipe for target 'main' failed
make: *** [main] Error 1

任何帮助都会很高兴地得到一个拥抱和一张我第一次乘坐我的时间机器的门票!提前致谢!

【问题讨论】:

    标签: c cuda makefile openmp nvcc


    【解决方案1】:

    您的 main.c 文件需要指向 myfunc_CUDA 的 c++ 可链接入口点,但您的 mylib_cuda.cu 文件正在导出指向该函数的 c 可链接入口点。

    我能够通过修改您的 main.c 中的包含序列以匹配您在其他地方所做的事情来纠正您描述的问题:

    #include "../include/mylib_omp.h"
    extern "C"{
    #include "../include/mylib_cuda.h"
    }
    

    不过,实现此目的的方法不止一种。由于您明确指定nvcc 有问题的文件将被编译为 c++ 源代码 (-x c++) 我不确定是否需要将任何内容导出为 c-linkable。您应该能够丢弃所有 extern "C" 装饰并获得相同的结果。 C++ 链接将解决所有问题。

    顺便说一句,我不确定在编译.cu 文件时将-x c++ 切换到nvcc 是否有意义。我认为这是有效的,因为您的mylib_cuda.cu 文件中没有实际的设备代码,只有一个 CUDA API 调用(即使在 C++ 文件中也是合法的)。如果您实际上将设备代码放入该文件(例如内核函数),我认为您将无法使用该文件上的-x c++ 开关。您不妨参考nvccdocumentation

    【讨论】:

    • 太棒了!谢谢你。这至少解决了这个错误。现在我被其他我从未遇到过的东西困住了。我删除了所有“extern”的东西和“-x c++”选项。其他一切都没有改变。但是现在我通过 make 得到以下错误:nvcc -arch=sm_12 -ccbin=g++-4.4 -Xcompiler -openmp -I include -I/opt/cuda/include -L/opt/cuda/lib64 -c -o sources/mylib_cuda.o sources/mylib_cuda.cu cc1plus: Fehler: Ausgabedatei doppelt angegeben Makefile:30: recipe for target 'sources/mylib_cuda.o' failed make: *** [sources/mylib_cuda.o] Error 1 关于那个有什么注释吗?提前致谢!
    • 对于gccg++ 我不认为-openmpvalid compile switch。请改用-fopenmp
    • 在进一步谷歌搜索之后,我发现了两个选项'-fopenmp lgomp',但现在旧错误又回来了,还有更多:('sources/main.o: In function main': main.c:(.text+0x12): undefined reference to myfunc_CUDA' sources/mylib_omp .o: 在函数myfunc_OMP': mylib_omp.c:(.text+0x20): undefined reference to GOMP_parallel_start' mylib_omp.c:(.text+0x2f): 未定义引用GOMP_parallel_end' sources/mylib_omp.o: In function myfunc_OMP.omp_fn.0': mylib_omp.c:(.text+0x43): 未定义引用@987654345 @omp_get_thread_num''
    • 这不是旧错误。在编译过程中你需要-fopenmp。在链接过程中,您需要-lgomp 而不是lgomp 您现在面临的问题是由于缺少-lgomp
    • 感谢您的耐心等待!我想当谈到'omp'部分时,我现在明白了。 “同样的错误”我指的是 make 输出的第一行,它抱怨“未定义对 myfunc_CUDA 的引用”,这确实是仍然存在的原始错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    相关资源
    最近更新 更多