首页 > 解决方案 > 使用 CUDA 代码编译 MINPACK 库的问题

问题描述

我需要求解一个非线性方程组,我找到了 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

我的主要文件是:

主文件

#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/

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

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

编辑

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 */
...

标签: c++cmakefilecuda

解决方案


根据talonmies 的评论,我能够编译在文件中定义__device__函数的代码。dpmparmain.cu

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

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

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

现在代码编译好了!!


推荐阅读