You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PGI PGCC编译链接LAPACK/BLAS库报未定义引用如何解决

问题根因

当前配置存在4个核心错误:

  • 编译器选型错误:pgcc是NVIDIA HPC SDK(原PGI)提供的纯C编译器,不支持C语法(包括extern "C"链接声明),用其编译.cpp后缀的C源文件本身就不匹配,这也是之前添加extern "C"后直接编译失败的核心原因。
  • 库路径配置生效阶段错误:LD_LIBRARY_PATH是程序运行阶段查找动态依赖库的环境变量,编译链接阶段不会读取该变量,未在链接参数中明确指定LAPACK/BLAS库存放路径时,链接器会在默认搜索路径中查找,无法定位到NVHPC安装目录下的库文件。
  • 函数声明错误:BLAS、LAPACK均为Fortran实现的库,dgemm_、dgesvd_属于Fortran子例程,无返回值,对应C/C++中的返回值类型为void,原声明写为int返回值,即使链接成功也会触发调用栈错误。
  • 链接参数逻辑错误:库路径参数需要放在链接项最前方,原配置未指定路径直接写库名,链接器无法定位到目标库。
修复步骤
  1. 调整Makefile配置,替换C++编译器为NVHPC配套的pgc++,补充链接阶段库搜索路径,修正后的Makefile如下:
LIBRARIES := -lm
# C++编译使用pgc++,保留原OpenACC编译选项
PGCXX = pgc++ -Minfo=accel -fast -acc -ta=multicore -tp=nehalem -DDEBUG
# 显式指定链接阶段库搜索路径
LIB_SEARCH_PATH := -L/opt/nvidia/hpc_sdk/Linux_x86_64/21.9/compilers/lib/
CFLAGS = -O3

################################################################################
all: build
build: VD

VD.o: VD.cpp
	$(PGCXX) -o $@ -c $< -w

VD: VD.o
	$(PGCXX) $(CFLAGS) -o $@ $+ $(LIB_SEARCH_PATH) -llapack -lblas $(LIBRARIES)

clean:
	rm -f VD.o VD

可选优化:若需要更好的多核性能,可将-llapack -lblas替换为-mkl=multicore(需安装Intel MKL)或-lacml -lacml_mv(NVHPC自带优化BLAS库,关联LAPACK自动链接),性能优于通用开源BLAS/LAPACK实现。

  1. 修正源文件中的函数声明,使用extern "C"包裹Fortran库函数声明,避免C++名字修饰导致符号不匹配,同时修正返回值类型:
// 原有标准库、OpenACC头文件、宏定义保持不变

// 用extern "C"块包裹Fortran库函数声明,指定使用C链接规则
extern "C" {
    // 修正返回值为void,Fortran子例程无返回值
    void dgemm_(char *transa, char *transb, int *m, int *
            n, int *k, double *alpha, double *a, int *lda,
            double *b, int *ldb, double *beta, double *c, int
            *ldc);

    void dgesvd_(char *jobu, char *jobvt, int *m, int *n,
        double *a, int *lda, double *s, double *u, int *
        ldu, double *vt, int *ldvt, double *work, int *lwork,
        int *info);
}

说明:之前添加extern "C"编译失败,完全是因为误用纯C编译器pgcc编译C++代码,C编译器不识别extern "C"语法,替换为pgc++后该问题会自动解决。

  1. 重新编译前先执行make clean清除旧的目标文件,再执行make即可完成编译链接。若仍提示符号找不到,可执行nm /opt/nvidia/hpc_sdk/Linux_x86_64/21.9/compilers/lib/liblapack.so | grep dgesvd查看库内实际符号名,若符号名不带尾部下划线,对应去掉函数名末尾的_即可。

内容的提问来源于stack exchange,提问作者gamersensual

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 05:24:52