专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
开发者全社区  ·  出来相亲了 ·  12 小时前  
开发者全社区  ·  春晚差点穿帮的镜头 ·  15 小时前  
开发者全社区  ·  跳崖了 ·  昨天  
鸿洋  ·  GPU硬件加速提升渲染流畅度 ·  昨天  
开发者全社区  ·  大S走了,两任老公争遗产式撕逼表演 ·  2 天前  
51好读  ›  专栏  ›  安卓开发精选

从源码看DL4J中Native BLAS的加载,以及配置(上)

安卓开发精选  · 公众号  · android  · 2016-11-24 23:37

正文

(点击 上方公众号 ,可快速关注)


来源:伯乐在线专栏作者 - 望天

链接: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" ,







请到「今天看啥」查看全文