Fortran90 中的 BLAS 函数 returns 零
BLAS function returns zero in Fortran90
我正在学习在Fortran90中使用BLAS,并使用子程序编写了一个简单的程序SAXPY and the function SNRM2。该程序通过一个向量减去另一个向量来计算两点之间的距离,然后取结果的欧几里德范数。
根据类似问题的回答,我将SNRM2的return值指定为external
。
我的完整程序:
program test
implicit none
real :: dist
real, dimension(3) :: a, b
real, external :: SNRM2
a = (/ 3.0, 0.0, 0.0 /)
b = (/ 0.0, 4.0, 0.0 /)
call SAXPY(3, -1.0, a,1, b,1)
print *, 'difference vector: ', b
dist = 6.66 !to show that SNRM2 is doing something
dist = SNRM2(3, b, 1)
print *, 'length of diff vector: ', dist
end program test
程序的结果是:
difference vector: -3.00000000 4.00000000 0.00000000
length of diff vector: 0.00000000
差异向量是正确的,但长度应该是5。那么为什么SNRM2 returning 的值为零?
我知道变量 dist
被 SNRM2 修改了,所以我不怀疑我的 openBLAS 安装有问题。我是 运行 macos10.13 并用自制软件安装了所有东西。
我在启用许多标志的情况下使用 gfortran 进行编译,但没有收到任何警告:
gfortran test.f90 -lblas -g -fimplicit-none -fcheck=all -fwhole-file -fcheck=all -fbacktrace -Wall -Wextra -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wconversion -Wno-unused-parameter -pedantic -o test
我尝试查看 the code for snrm2.f,但没有发现任何潜在问题。
我还尝试使用 real(4)
或 real(selected_real_kind(6))
声明我的变量,但行为没有变化。
谢谢!
根据此 page,Apple 的 Accelerate Framework 附带的 BLAS 中的单精度例程似乎存在一些问题。
在我的 Mac (OSX10.11) 上,gfortran-8.1(通过 Homebrew 安装)+ 默认 BLAS(在系统中)给出了错误的结果:
$ gfortran-8 test.f90 -lblas
or
$ gfortran-8 test.f90 -L/System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/Versions/Current/ -lBLAS
$ ./a.out
difference vector: -3.00000000 4.00000000 0.00000000
length of diff vector: 0.00000000
显式链接 OpenBLAS(通过 Homebrew 安装)时给出正确的结果:
$ gfortran-8 test.f90 -L/usr/local/Cellar/openblas/0.2.20_2/lib -lblas
$ ./a.out
difference vector: -3.00000000 4.00000000 0.00000000
length of diff vector: 5.00000000
以上页面表明问题发生在以不符合旧 g77 样式的方式与系统 BLAS 链接时。事实上,附加 -ff2c
选项给出了正确的结果:
$ gfortran-8 -ff2c test.f90 -lblas
$ ./a.out
difference vector: -3.00000000 4.00000000 0.00000000
length of diff vector: 5.00000000
但我想使用最新的 OpenBLAS 可能更好(比使用 -ff2c
选项)...
以下是 C 中的单独测试(以检查问题是否特定于 gfortran)。
// test.c
#include <stdio.h>
float snrm2_( int*, float*, int* );
int main()
{
float b[3] = { -3.0f, 4.0f, 0.0f };
int n = 3, inc = 1;
float dist = snrm2_( &n, b, &inc );
printf( "b = %10.7f %10.7f %10.7f\n", b[0], b[1], b[2] );
printf( "dist = %10.7f\n", dist );
return 0;
}
$ gcc-8 test.c -lblas
$ ./a.out
b = -3.0000000 4.0000000 0.0000000
dist = 0.0000000
$ gcc-8 test.c -lblas -L/usr/local/Cellar/openblas/0.2.20_2/lib
$ ./a.out
b = -3.0000000 4.0000000 0.0000000
dist = 5.0000000
据我所知,双精度版本 (DNRM2) 即使在系统 BLAS 上也能正常工作,所以问题似乎只出现在单精度版本上(如上页所示)。
我正在学习在Fortran90中使用BLAS,并使用子程序编写了一个简单的程序SAXPY and the function SNRM2。该程序通过一个向量减去另一个向量来计算两点之间的距离,然后取结果的欧几里德范数。
根据类似问题external
。
我的完整程序:
program test
implicit none
real :: dist
real, dimension(3) :: a, b
real, external :: SNRM2
a = (/ 3.0, 0.0, 0.0 /)
b = (/ 0.0, 4.0, 0.0 /)
call SAXPY(3, -1.0, a,1, b,1)
print *, 'difference vector: ', b
dist = 6.66 !to show that SNRM2 is doing something
dist = SNRM2(3, b, 1)
print *, 'length of diff vector: ', dist
end program test
程序的结果是:
difference vector: -3.00000000 4.00000000 0.00000000
length of diff vector: 0.00000000
差异向量是正确的,但长度应该是5。那么为什么SNRM2 returning 的值为零?
我知道变量 dist
被 SNRM2 修改了,所以我不怀疑我的 openBLAS 安装有问题。我是 运行 macos10.13 并用自制软件安装了所有东西。
我在启用许多标志的情况下使用 gfortran 进行编译,但没有收到任何警告:
gfortran test.f90 -lblas -g -fimplicit-none -fcheck=all -fwhole-file -fcheck=all -fbacktrace -Wall -Wextra -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wconversion -Wno-unused-parameter -pedantic -o test
我尝试查看 the code for snrm2.f,但没有发现任何潜在问题。
我还尝试使用 real(4)
或 real(selected_real_kind(6))
声明我的变量,但行为没有变化。
谢谢!
根据此 page,Apple 的 Accelerate Framework 附带的 BLAS 中的单精度例程似乎存在一些问题。 在我的 Mac (OSX10.11) 上,gfortran-8.1(通过 Homebrew 安装)+ 默认 BLAS(在系统中)给出了错误的结果:
$ gfortran-8 test.f90 -lblas
or
$ gfortran-8 test.f90 -L/System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/Versions/Current/ -lBLAS
$ ./a.out
difference vector: -3.00000000 4.00000000 0.00000000
length of diff vector: 0.00000000
显式链接 OpenBLAS(通过 Homebrew 安装)时给出正确的结果:
$ gfortran-8 test.f90 -L/usr/local/Cellar/openblas/0.2.20_2/lib -lblas
$ ./a.out
difference vector: -3.00000000 4.00000000 0.00000000
length of diff vector: 5.00000000
以上页面表明问题发生在以不符合旧 g77 样式的方式与系统 BLAS 链接时。事实上,附加 -ff2c
选项给出了正确的结果:
$ gfortran-8 -ff2c test.f90 -lblas
$ ./a.out
difference vector: -3.00000000 4.00000000 0.00000000
length of diff vector: 5.00000000
但我想使用最新的 OpenBLAS 可能更好(比使用 -ff2c
选项)...
以下是 C 中的单独测试(以检查问题是否特定于 gfortran)。
// test.c
#include <stdio.h>
float snrm2_( int*, float*, int* );
int main()
{
float b[3] = { -3.0f, 4.0f, 0.0f };
int n = 3, inc = 1;
float dist = snrm2_( &n, b, &inc );
printf( "b = %10.7f %10.7f %10.7f\n", b[0], b[1], b[2] );
printf( "dist = %10.7f\n", dist );
return 0;
}
$ gcc-8 test.c -lblas
$ ./a.out
b = -3.0000000 4.0000000 0.0000000
dist = 0.0000000
$ gcc-8 test.c -lblas -L/usr/local/Cellar/openblas/0.2.20_2/lib
$ ./a.out
b = -3.0000000 4.0000000 0.0000000
dist = 5.0000000
据我所知,双精度版本 (DNRM2) 即使在系统 BLAS 上也能正常工作,所以问题似乎只出现在单精度版本上(如上页所示)。