Неразрешенная ссылка на dgemm при использовании OpenBLAS

Некоторое время я пытался скомпилировать и связать библиотеку OpenBLAS для умножения на матрицы вместе с помощью dgemm. Наконец-то я смог скомпилировать OpenBLAS после установки MSYS2 и пакетов mingw64 из MSYS2 с помощью pacman. Я намерен использовать OpenBLAS в качестве статической библиотеки. Поэтому я написал простой код на Фортране для перемножения матриц с помощью dgemm. Вот код фортрана:

program gcc_fun

 implicit none
            
! Variables
 real*8 x(2,2),y(2,2),z(2,2)

 x(1,1) = 3.d0
 x(2,1) = 2.d0
 x(1,2) = 1.d0
 x(2,2) = 4.d0
 y(1,1) = .5d0
 y(2,1) = 1.d0
 y(1,2) = 2.d0
 y(2,2) = .75d0
 
    call dgemm( 'n', 'n', 2, 2, 2, 1,x,2,y, 2, 1, z, 1)

! Body of gcc_fun
print *, 'Z = ', z

end program gcc_fun

Вот мой make-файл, чтобы попробовать и связать:

CCC      = gcc   -g -Iincludem -Iincludev   -c   -O0
WARN     = -Wall
CCCX     = x86_64-w64-mingw32-g++  -m64 -s -Iincludem -Iincludev   -c   -O2 -DNDEBUG
fort     = x86_64-w64-mingw32-gfortran -s -Iincludem -Iincludev -fno-underscoring -c   -O2 -DNDEBUG
#fort     = x86_64-w64-mingw32-gfortran -s -Iincludem -Iincludev -c   -O2 -DNDEBUG

OBJECTS = \
     obj/gcc_fun.o 



          
#-----------------------------------------------------------------------------------
#  Make the Guidance Object Library (GNC_Lib.a) and the Executable (guideUnitTest)
#-----------------------------------------------------------------------------------


gcc_fun.exe:  $(OBJECTS)
    x86_64-w64-mingw32-gfortran -o gcc_fun.exe   -L./ -lopenblas_haswell-r0.3.10  $(OBJECTS) 

#------------------------------------------
#                object file targets 
#------------------------------------------

    
obj/gcc_fun.o: \
gcc_fun.f90
    $(fort) $(WARN) -o $@ gcc_fun.f90

Я запускаю make-файл с make -f makefile_name и получаю неразрешенную ссылку на dgemm. Я пробовал это с опцией «без подчеркивания» и без нее, но безрезультатно. Вот собственно ошибка:

$ make -f Makefile_gcc_fun.mak
x86_64-w64-mingw32-gfortran -s -Iincludem -Iincludev -fno-underscoring -c   -O2 -DNDEBUG -Wall -o obj/gcc_fun.o gcc_fun.f90
f951.exe: Warning: Nonexistent include directory 'includem' [-Wmissing-include-dirs]
f951.exe: Warning: Nonexistent include directory 'includev' [-Wmissing-include-dirs]
gcc_fun.f90:27:2:

   27 |   x(2,1) = 2.d0
      |  1
Warning: Nonconforming tab character at (1) [-Wtabs]
gcc_fun.f90:28:2:

   28 |   x(1,2) = 1.d0
      |  1
Warning: Nonconforming tab character at (1) [-Wtabs]
gcc_fun.f90:29:2:

   29 |   x(2,2) = 4.d0
      |  1
Warning: Nonconforming tab character at (1) [-Wtabs]
gcc_fun.f90:31:2:

   31 |   y(2,1) = 1.d0
      |  1
Warning: Nonconforming tab character at (1) [-Wtabs]
gcc_fun.f90:32:2:

   32 |   y(1,2) = 2.d0
      |  1
Warning: Nonconforming tab character at (1) [-Wtabs]
gcc_fun.f90:33:2:

   33 |   y(2,2) = .75d0
      |  1
Warning: Nonconforming tab character at (1) [-Wtabs]
x86_64-w64-mingw32-gfortran -o gcc_fun.exe   -L./ -lopenblas_haswell-r0.3.10  obj/gcc_fun.o
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: obj/gcc_fun.o:gcc_fun.f90:(.text+0xf5): undefined reference to `dgemm'
collect2.exe: error: ld returned 1 exit status
make: *** [Makefile_gcc_fun.mak:19: gcc_fun.exe] Error 1

Когда я проверяю библиотеку OpenBLAS с помощью nm, я получаю следующее:

$ nm -g libopenblas_haswell-r0.3.10.a | grep dgemm
dgemm.obj:
0000000000000000 T dgemm_

Итак, похоже, что dgemm — это внешний объект, и я должен иметь возможность вызывать его. Я уверен, что мне не хватает чего-то легкого, поэтому спасибо за любую помощь.


person David Alldredge    schedule 01.09.2020    source источник


Ответы (1)


Подпрограмма просто dgemm, а не dgemm_. Вы просто называете это

call dgemm()

Имя символа, которое вы видите с помощью nm, может отличаться в зависимости от вашей цепочки инструментов (компилятор, операционная система,...). Имеет значение, если вы делаете интероперабельность разных языков программирования. Однако, если вы остаетесь в Fortran, вам не нужно беспокоиться об этом.


Важный:

Связываемая статическая библиотека должна быть помещена после файла, который использует библиотеку в команде связывания. Только тогда зависимости могут быть разрешены. Если это реальная проблема, у нас будет несколько дубликатов, на которые можно сослаться.

person Vladimir F    schedule 01.09.2020
comment
Спасибо за комментарий. Я попробовал это только с call dgemm, и ошибка изменилась на undefined reference to dgemm - person David Alldredge; 01.09.2020
comment
@DavidAlldredge Но почему вы используете -fno-underscoring? Или он действительно используется или нет? Какова цель вашего fort в Makefile? Он вообще используется? - person Vladimir F; 01.09.2020
comment
Эти простые примеры взяты из моего фактического приложения, которое представляет собой смесь кода fortran, c, c++. Там мне нужно, чтобы fortran не добавлял _. Итак, вариант без подчеркивания. В этом простом примере я просто пытался заставить это работать, прежде чем переходить к более крупному и сложному приложению. Так как я впервые пытаюсь слинковать OpenBLAS, я не уверен, что правильно скомпилировал его с помощью кросс-компиляторов mingw_w64. Если этот простой пример должен работать так, как показано, то я предполагаю, что что-то в том, как я скомпилировал OpenBLAS? - person David Alldredge; 01.09.2020
comment
Я только что увидел ваш измененный комментарий. Я определяю fort, а затем использую его для компиляции файла .f90, показанного в верхней части этой страницы. - person David Alldredge; 01.09.2020
comment
@DavidAlldredge Но в выводе компилятора, который вы показываете, нет --fno-underscoring. Я вообще не вижу, как используется fort. Пожалуйста, опубликуйте полный вывод, включая все шаги компиляции. Перед этим сделайте make clean (или просто удалите все файлы .o). - person Vladimir F; 01.09.2020
comment
Я обновил основной пост, чтобы показать результаты чистой компиляции. Я показал только один с no-underscoring, но получаю ту же ошибку, за исключением неразрешенной ссылки, измененной с dgemm на dgemm_ - person David Alldredge; 01.09.2020
comment
Ваша командная строка не содержит библиотеки. Вам нужно сообщить gfortran, где найти библиотеку и название библиотеки. Возможно, -L{путь_к_библиотеке} -lopenblas - person evets; 02.09.2020
comment
@evets Используется некоторый `-L./ -lopenblas_haswell-r0.3.10`, но он помещен в команду слишком рано, его следует поместить после имени файла .o. - person Vladimir F; 02.09.2020
comment
@Владимир, да, я понял это примерно через 10 секунд после публикации. При использовании статических библиотек и объектных файлов порядок имеет значение. - person evets; 02.09.2020
comment
Ха! Я знал, что это была глупая ошибка с моей стороны. Итак, теперь он компилируется, но exec терпит неудачу, потому что он ищет libgfortran-5.dll Приложение, которое я в конечном итоге создам, должно будет работать на любом компьютере с Windows и может не иметь fortran (опять же, почему я хочу статически связать OpenBLAS) Можно ли исправить эту новую ошибку? с -static или связывая 'lgfortran или что-то еще? Я очень ценю помощь. - person David Alldredge; 02.09.2020
comment
Итак, я попробовал -static, и, по крайней мере, для простого примера это сработало. Спасибо за все комментарии!!!!!! - person David Alldredge; 02.09.2020