(点击
上方公众号
,可快速关注)
来源:伯乐在线专栏作者 - 望天
链接:http://android.jobbole.com/85213/
点击 → 了解如何加入专栏作者
最近在用DeepLearning4J(DL4J)尝试语音识别的深度学习,Git DL4J的代码,用IntelliJ IDEA打开,配置好相关依赖后,运行包org.deeplearning4j.examples.test.Test的main,可以正常运行,但是有警告提示如下:
十一月
27
,
2015
12
:
37
:
07
下午
com
.
github
.
fommil
.
netlib
.
BLAS
WARNING
:
Failed
to
load implementation
from
:
com
.
github
.
fommil
.
netlib
.
NativeSystemBLAS
十一月
27
,
2015
12
:
37
:
09
下午
com
.
github
.
fommil
.
jni
.
JniLoader
liberalLoad
****************************************************************
INFO
:
successfully
loaded
C
:
\
Users
\
ADMINI
~
1
\
AppData
\
Local
\
Temp
\
jniloader6882206374132167742netlib
-
native_ref
-
win
-
x86_64
.
dll
WARNING
:
COULD
NOT
LOAD
NATIVE
SYSTEM BLAS
ND4J performance WILL be reduced
Please install
native
BLAS library such
as
OpenBLAS
or
IntelMKL
See
http
:
//nd4j.org/getstarted.html#open for further details
****************************************************************
提示无法加载com.github.fommil.netlib.NativeSystemBLAS,和无法加载native system blas,DN4J的性能会受到影响.
查了github,stackoverflow,quora等,找到了如下网页.github的是一个遇到类似问题的人抱怨native blas难以配置,害的自己在源码中才找到解决方法,而nd4j的程序员回答所有的深度学习框架中的native blas都是难配置的,我在搜索的时候也发现了MLib等库确实也会报这个警告.第二个博客是一篇讲述如何配置blas的文章.
https
:
//github.com/deeplearning4j/nd4j/issues/456
http
:
//avulanov.blogspot.cz/2014/09/howto-to-run-netlib-javabreeze-in.html
这篇文章中,我想说明一下几个问题:
1. native blas 是本地库,用C/C++写成,因而运算速度较快.
2. Java如果要调用C/C++的dll,一定要用JNI技术来调用对应的dll,那么dll的路径和名称分别是什么?
3. 如果找到需要的dll,假设叫a.dll,如果a.dll又依赖于b.dll和c.dll,那么把a.dll,b.dll,c.dll都放在Java识别的路径下,是不是就可以解决这个问题了.
1.dll的存放路径和名称
先看DL4J的源码,错误首先出现在如下代码中
Nd4j
.
getRandom
().
setSeed
(
seed
);
进入Nd4j的类,加断点,单步调试,经过如下的函数调用栈后,进入NativeSystemBLAS这个类.
我们看下NativeSystemBLAS类的内容,在static静态块中找到如下用于加载dll的代码:
static
{
String
jnilib
=
JniNamer
.
getJniName
(
"netlib-native_system"
);
String
natives
=
System
.
getProperty
(
"com.github.fommil.netlib.NativeSystemBLAS.natives"
,
jnilib
);
JniLoader
.
load
(
natives
.
split
(
","
));
}
先加断点单步运行,看看jnilib的内容,运行后得到的是”netlib-native_system-win-x86_64.dll”,为什么是这个,我的电脑是64位,如果32位系统又会需要哪个dll库呢?
我们进入getJniName函数,看下其代码,这里arch用于获得架构,os用于获得系统版本,extension获得后缀,然后拼出dll的名称:
public
static
String
getJniName
(
String
stem
)
{
String
arch
=
arch
();
//获得系统架构,x86,i386对应于i686,x86_64,amd64对应于x86_64,其他还有arm等架构
String
abi
=
abi
(
arch
);
//判断是不是arm架构,如果是arm架构,需要其他的设置,这里不问
String
os
=
os
();
//判断系统是win,linux.还是mac os x
String
extension
=
extension
(
os
);
//根据系统版本,确定文件后缀名是dll,还是so,osx
return
stem
+
"-"
+
os
+
"-"
+
arch
+
abi
+
"."
+
extension
;
//返回确定的库名字
}
arch代码如下:
private
static
String
arch
()
{
String
arch
=
System
.
getProperty
(
"os.arch"
,
""
).
toLowerCase
();
if
(
!
arch
.
equals
(
"x86"
)
&& !
arch
.
equals
(
"i386"
)
&& !
arch
.
equals
(
"i486"
)
&& !
arch
.
equals
(
"i586"
)
&& !
arch
.
equals
(
"i686"
))
{
if
(
!
arch
.
equals
(
"x86_64"
)
&& !
arch
.
equals
(
"amd64"
))
{
if
(
arch
.
equals
(
"ia64"
))
{
return
"ia64"
;
}
else
if
(
arch
.
equals
(
"arm"
))
{
return
"arm"
;
}
else
if
(
arch
.
equals
(
"armv5l"
))
{
return
"armv5l"
;
}
else
if
(
arch
.
equals
(
"armv6l"
))
{
return
"armv6l"
;
}
else
if
(
arch
.
equals
(
"armv7l"
))
{
return
"armv7l"
;
}
else
if
(
arch
.
equals
(
"sparc"
))
{
return
"sparc"
;
}
else
if
(
arch
.
equals
(
"sparcv9"
))
{
return
"sparcv9"
;
}
else
if
(
arch
.
equals
(
"pa_risc2.0"
))
{
return
"risc2"
;
}
else
if
(
arch
.
equals
(
"ppc"
))
{
return
"ppc"
;
}
else
if
(
arch
.
startsWith
(
"ppc"
))
{
return
"ppc64"
;
}
else
{
log
.
warning
(
"unrecognised architecture: "
+
arch
);
return
"unknown"
;
}
}
else
{
return
"x86_64"
;
}
}
else
{
return
"i686"
;
}
}
abi代码如下:
private
static
String
abi
(
String
arch
)
{
if
(
!
arch
.
startsWith
(
"arm"
))
{
return
""
;
}
else
{
try
{
String
[]
e
=
new
String
[]{
"sun.boot.library.path"
,
"java.library.path"
,
"java.home"
};
int
len
$
=
e
.
length
;
int
i
$;
String
dir
;
for
(
i
$
=
0
;
i
$
len
$;
++
i
$)
{
dir
=
e
[
i
$];
String
file
=
System
.
getProperty
(
dir
,
""
);
log
.
config
(
dir
+
": "
+
file
);
if
(
file
.
matches
(
".*(gnueabihf|armhf).*"
))
{
return
"hf"
;
}
}
e
=
new
String
[]{
"/lib/arm-linux-gnueabihf"
,
"/usr/lib/arm-linux-gnueabihf"
};
len
$
=
e
.
length
;
for
(
i
$
=
0
;
i
$
len
$;
++
i
$)
{
dir
=
e
[
i
$];
File
var7
=
new
File
(
dir
);
if
(
var7
.
exists
())
{
return
"hf"
;
}
}
return
""
;
}
catch
(
SecurityException
var6
)
{
log
.
log
(
Level
.
WARNING
,
"unable to detect ABI"
,