【问题标题】:Problem in compilation of MINPACK library with CUDA code使用 CUDA 代码编译 MINPACK 库的问题
【发布时间】:2021-05-31 04:33:20
【问题描述】:

我需要求解一个非线性方程组,我找到了 MINPACK 库来完成这项工作。 但我需要代码才能与 CUDA 一起使用,但我无法编译代码。

我正面临这个问题:

nvcc -arch sm_61 -Iinc -I/usr/local/include obj/main.o -o oi -L/usr/local/lib64 -lcuminpack
nvlink error   : Undefined reference to 'dpmpar' in 'obj/main.o'
make: *** [makefile:55: oi] Erro 255

我的主要文件是:

ma​​in.cu

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

#define __cminpack_double__
#include <cminpack-1/cminpack.h>
#define real __cminpack_real__

typedef struct{
  real fnorm1, fnorm2;
  int info;
  real solution[2];
} ResultType;

__cminpack_attr__ int fcn(void *p, int n, const real *x, real *fvec, int iflag){

    --fvec;
    --x;

    fvec[0] = x[0] + x[0]*x[1] - 4.0;
    fvec[1] = x[0] + x[1] -3.0;

    return 0;
}

__global__ void SolvingSystem(ResultType *pResults){

    int info;

    real fnorm1, fnorm2, tol;

    int n = 2;

    real fvec[2];
    real x[2];

    const int lwa = (n*(3*n + 13))/2;
    real wa[50];

    tol = sqrt(dpmpar(1));

    x[0] = 1.98;
    x[1] = 1.02;

    printf("Initial Guess: %g, %g\n", x[0], x[1]);
}

int main(int argc, char const *argv[]){
    
    cudaSetDevice(0);

    ResultType *reuslt_GPU, *reuslt_CPU;

    cudaMalloc((void**)&reuslt_GPU, sizeof(ResultType));
    cudaMallocHost((void**)&reuslt_CPU, sizeof(ResultType));

    printf("Solving System...\n");

    dim3 grid(1, 1, 1);
    dim3 block(1, 1, 1);

    SolvingSystem<<< grid, block>>>(reuslt_GPU);

    cudaDeviceSynchronize();
    printf("Done!\n");

    return 0;
}

我的makefile是:

制作文件

# MakeFile

# Program Name
EXE = oi

# Compilers
NVCC := nvcc

ALL_LIBRARIES := cuminpack
LIBDIR :=  /usr/local/lib64

# Directories
SRCDIR := src
OBJDIR := obj
INCDIR := inc /usr/local/include

#Flags
NVCCARCHFLAG := -arch sm_61
NVCCFLAGS    := -std=c++11
LDFLAGS      := $(addprefix -L, $(LIBDIR))

INCLUDES     := $(addprefix -I, $(INCDIR))
LIBRARIES    := $(addprefix -l, $(ALL_LIBRARIES))
LIBRARIES    += 

ALL_CPFLAGS := -MMD
ALL_CPFLAGS += $(NVCCARCHFLAG)
ALL_CPFLAGS += $(NVCCFLAGS)

ALL_LDFLAGS := $(LDFLAGS)


# Files
C_FILES := $(wildcard $(SRCDIR)/*.c)
CU_FILES := $(wildcard $(SRCDIR)/*.cu)

C_OBJ := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(C_FILES))
CU_OBJ := $(patsubst $(SRCDIR)/%.cu, $(OBJDIR)/%.o, $(CU_FILES))

C_DEP := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.d, $(C_FILES))
CU_DEP := $(patsubst $(SRCDIR)/%.cu, $(OBJDIR)/%.d, $(CU_FILES))

SRC := $(C_FILES) $(CU_FILES)
OBJ := $(C_OBJ) $(CU_OBJ)
DEP := $(C_DEP) $(CU_DEP)

COMPILE.c := $(NVCC) -MMD -g $(INCLUDES) -c
COMPILE.cu := $(NVCC) $(ALL_CPFLAGS) $(INCLUDES) -dc

.PHONY: all clean

all:$(EXE)

$(EXE): $(OBJ)
    $(NVCC) $(NVCCARCHFLAG) $(INCLUDES) $^ -o $@ $(ALL_LDFLAGS) $(LIBRARIES)

$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
    $(COMPILE.c) $< -o $@

$(OBJDIR)/%.o: $(SRCDIR)/%.cu | $(OBJDIR)
    $(COMPILE.cu) $< -o $@

$(OBJDIR):
    @mkdir -p $@

# Cleaning up
clean:
    @echo Cleaning up...
    @rm -f -r $(OBJDIR)
    @rm $(EXE)


# Including dependency
-include $(DEP)

主文件需要完成,这就是一些未使用变量的原因。

我只是不知道是什么导致了这个错误,我认为问题出在 cuminpack 库中,但我现在不知道如何解决它。

我正在使用来自该网站的 cminpack-1.3.8:http://devernay.free.fr/hacks/cminpack/

我使用cmake 然后makemake install 安装了库。然后我去了源文件夹并做了make cuda。最后一条命令在cuda 目录中生成了libcuminpack.a 文件,然后我将此.a 文件复制到了cmake 安装其他库文件的/usr/local/lib64

如果有人能帮助我,我将非常感激

编辑

来自 cminpack 库的文件

cminpack.h

...
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
...
#if defined(__CUDA_ARCH__) || defined(__CUDACC__)
#define __cminpack_attr__ __device__
#ifndef __cminpack_real__
#define __cminpack_float__
#define __cminpack_real__ float
#endif
#define __cminpack_type_fcn_nn__        __cminpack_attr__ int fcn_nn
#define __cminpack_type_fcnder_nn__     __cminpack_attr__ int fcnder_nn
#define __cminpack_type_fcn_mn__        __cminpack_attr__ int fcn_mn
#define __cminpack_type_fcnder_mn__     __cminpack_attr__ int fcnder_mn
#define __cminpack_type_fcnderstr_mn__  __cminpack_attr__ int fcnderstr_mn
#define __cminpack_decl_fcn_nn__
#define __cminpack_decl_fcnder_nn__
#define __cminpack_decl_fcn_mn__
#define __cminpack_decl_fcnder_mn__
#define __cminpack_decl_fcnderstr_mn__
#define __cminpack_param_fcn_nn__
#define __cminpack_param_fcnder_nn__
#define __cminpack_param_fcn_mn__
#define __cminpack_param_fcnder_mn__
#define __cminpack_param_fcnderstr_mn__
...
__cminpack_attr__
__cminpack_real__ CMINPACK_EXPORT __cminpack_func__(dpmpar)( int i );

dpmpar.c

#include "cminpack.h"
#include <float.h>
#include "cminpackP.h"

#define DPMPAR(type,X) _DPMPAR(type,X)
#define _DPMPAR(type,X) type ## _ ## X

__cminpack_attr__
real __cminpack_func__(dpmpar)(int i)
{
/*     ********** */

/*     Function dpmpar */
...

【问题讨论】:

  • 您在 CUDA 内核中调用 dpmpar。这意味着要让它在那里工作 必须 有一个名为 dpmpar 的专用 CUDA __device__ 函数,它可以通过您导入的标头或在库中内联定义。如果它在库中,那么您必须使用 CUDA 单独编译和设备链接来构建代码。如果不是这两件事中的任何一个,那么您就处于神奇的思维领域,而您正在尝试做的是在 CUDA 内核中使用随机主机函数,而这永远不会起作用。我不能告诉你其中哪一项适用于这里
  • 我将部分头文件和 dpmpar.c 的开头从 cminpack 库添加到帖子中。如果我没记错的话,库作者通过__cminpack_attr__ 定义了__device__ 函数。所以,这意味着我需要使用 CUDA 单独编译和设备链接,对吗?但这不是用-dc 标志完成的吗?
  • 刚刚查看了库,我看到这个“cuda 需要与内核内联编译的 __device__ 源代码”。因此,您的整个构建过程将无法使用提供的此库。您也许可以从代码中创建自己的设备库,但据我所知,您需要自己为库创建一个新的 Makefile
  • 我想到了你说的解决了这个问题!!非常感谢!!
  • @MatheusIurk 是一种并行算法吗?我会很高兴错了,因为我认为这是连续剧。

标签: c++ c makefile cuda


【解决方案1】:

基于talonmies's 注释,我能够编译在main.cu 文件中定义__device__ 函数dpmpar 的代码。

然后我发现这篇帖子 https://forums.developer.nvidia.com/t/external-calls-to-device-functions/17737 那里的人回答说 CUDA 在设备端没有链接器,因此无法从不同的 .cu 文件调用 __device__ 函数。

考虑到这一点,我只从库中复制了我需要的文件并进行了一些修改,例如将__cminpack_attr__ 更改为__device__,并且我也重写了头文件。所以基本上我制作了自己的设备库(再次感谢talonmies's)。

我做的最后一件事是将所有这些新文件移动到我的main.cu 和我的makefile 所在的同一个文件夹中,我重写了makefile

现在代码编译好了!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-23
    • 2012-06-04
    • 2015-02-20
    • 2020-09-20
    • 1970-01-01
    相关资源
    最近更新 更多