找回密码
 注册
Simdroid-非首页
查看: 1040|回复: 8

[其他] 一些开源软件介绍(2)

[复制链接]
发表于 2011-6-13 01:11:11 | 显示全部楼层 |阅读模式 来自 英国
本帖最后由 myleader 于 2011-6-13 01:24 编辑

此前http://forum.simwe.com/viewthread.php?tid=931180
曾经讨论过豪华老爷车与后发优势。

Lapack在开源科学软件中的地位实在是太牢固了,此前有人写过一些软件,意图将其取而代之。这些挑战者中包括MTL、TNT等等,不过都没有成器,现在都已经处于长期不更新状态,事实上已经停止开发。而Boost中的ublas目前虽然还在进展,不过进展微乎其微。

这些软件之所以不能取代lapack,原因很复杂,不过对于科学运算的软件包而言,其实原因很简单:慢。Lapack是用Fortran写成的,Fortran写成的程序通常速度要快,当然这不是说C写不出那么快的程序,毕竟C可以在非常底层操作,只是Fortran可以把优化的任务交给编译器,而C大多需要程序员自己掌握,所以大多数人写出的C程序比Fortran要慢,而如果真的追求极速,那C程序的可读性就要大幅降低了。这一点在ublas上尤为明显,它的速度太慢了。

这次给大家隆重介绍一位新贵
http://eigen.tuxfamily.org/index.php?title=Main_Page

Eigen是用C++模板技术写成的数学软件包(此前MTL也曾经用模板技术意图在速度上超越Lapack,不过后来也不知道出了什么事情,项目几经易手,现在已经奄奄一息了。)不过Eigen正在前进,2011年5月刚刚发布了新一代的软件包,最新版本是3.0.1

大家可以访问
http://eigen.tuxfamily.org/index.php?title=Benchmark
看一看它和其他线性代数包的速度对比,其测试结果不逊于gotoblas和MKL。

更重要的是,它是用C++写成的,对于我这种不会使用Fortran的人而言,简直就是天大的福音

eigen是LGPL的,换句话说,只要你采用动态链接,那么你可以不开放你的源代码,eigen没有开源传染性

而且其文档非常详尽,基本上只要你熟悉C++就可以立即上手。虽然他的函数命名和MATLAB还是稍有不同,不过提供了一份对照表,照着做就可以了。

而且,它不需要使用lapack/blas作为后端,直接使用头文件和标准C库函数就可以了,这样采用eigen发布程序的时候就不需要额外附带一个lapack.dll了,而且其开发难度也大幅降低了。要知道,如果依赖lapack后端,就需要针对编译器和操作系统预先制作二进制库文件,而这个过程很烦的,还容易产生各种问题,如果将来你需要更换操作系统或者编译器,那就更烦了,如果你发布了程序,而用户使用的环境和你不一样,你还要专门再处理。有了eigen,可以甩开lapack.dll了

根据官方的说明,eigen适用于多种编译器,在中国使用最广泛的当然是微软的VC了,不过我个人更愿意使用mingw——主要因为它是绿色的,而且升级比较快,出了补丁可以自己装,微软的东西就算是报告了bug,也得等下一个新版本修正,而且mingw更新快的话,还可以很快追上最新的技术,比如多线程支持、最新的CPU指令集等等。

不过eigen毕竟年轻,很多功能还不完善。根据eigen官方的路线图,他们已经完全实现了blas的功能,但是lapack的功能还没有全部完成。不过eigen的目标并非简单的线性代数包,而是全功能。目前他们已经实现了openmp多线程支持,不过就像他们自己说的,openmp到底干了什么,他们并不清楚,所以线程安全是个问题;目前看来他们似乎两个方向都在考虑,一个是采用lapack作为后端,lapack/blas如果支持多线程,那就直接用,另一个是自己写多线程,不过工作量大,所以可能一时半会实现不了。另外,信号处理、统计学、优化……各种数学常用工具都在路线图中,而且实际上也出现在unsupported特性中,就是说这些特性也许可以用,不过官方目前不宣称可用,也就是试用的意思。

对我个人而言,现阶段blas的功能我用的倒是比lapack的多,所以不是十分在意这种事情。实在不行那就自己写点函数嘞,不过我估计官方不会接受我的源码的,我的水平比较烂

这个软件现在风头很大。原本是KDE的一个子项目,现在越做越大了,他们目前的主页上说法国科学院INRIA提供了一个工作岗位。说起来这个信号很暧昧,因为INRIA为了对抗MATLAB开发了一个开源的线性代数工具软件scilab,本来scilab的后端是lapack/blas,而且它的blas使用的是atlas,但是由于atlas在windows平台编译时需要Cygwin模拟环境,所以速度要慢很多,而且最新的3.8系列我是没编译出来,大概看了一下,scilab自带的atlas是3.6的。我个人还是更喜欢新版,因为新版总归是要解决旧版的一些问题的,而且3.6版最多只能支持到sse指令集,更新的就不行了,这样效能就差了很多。那么INRIA支持eigen说明什么呢?也许是觉得eigen可能在未来能够扛起与lapack分庭抗礼的大旗吧。

这个软件的安装也很简单,下载了源代码以后解压缩到硬盘上。然后到cmake网站下载一个cmake
http://www.cmake.org/cmake/resources/software.html
最新版是2.8.4
里面有一个gui工具,图形化的,很简单

启动cmake以后,第一项是源码目录,指定到刚刚解压缩的目录就好了

第二项是“构建目录”,其实就是说在构建过程中,会生成一些临时文件,而这些临时文件就放在这里,通常我会在源码目录下新建一个build子目录来充当这个角色。

然后点击configure,第一次会提示你选择编译器,我用的是mingw,就选mingw好了。不知道为什么,我的cmake第一次会出错,提示探测mingw编译器失败,不过再点一次就好了,然后它就会自动探测配置选项,然后出现在界面那个清单里

接下来对各个选项进行配置,最重要的一点是选择安装目录,其实安装过去也就是写头文件,不会写注册表或者配置文件,不过你如果搞错了到最后就会找不到了。这个目录设定在哪其实都可以,如果你想管理方便那就放在你自己的源码目录,如果你想用着方便,就放到编译器的include目录

其次还有一些选项在下面,重要的有这么几项:

1)openmp支持多线程,速度会提高,不过线程安全性不可控(或者说不是由eigen来控制的),我选了
2)sse系列指令集,提高速度用,根据gcc官方的说明,采用sse选项支持数学矢量运算会有计算错误的风险,不过我还是选了
3)x87,这个指的是x87数学协处理器指令集,主要包含了c库函数math.h中的功能,不过由于当年设计的不合理,现在这个指令集已经比较慢了,不要选
4)默认采用“行”存储。这个是矩阵在内存中的存储格式,Fortran默认都是“列”格式存储的,eigen默认也是“列”,这个看您意思,如果你需要和Fortran联合编程,最好不要选。不过在未来编写程序时这个可以在源代码里面设定
5)C++0x支持,我会选

其他的你自己把握就好了

然后点击generate,就会在build目录下生成Makefile和所需的文件,然后进入build目录,敲击命令
  1. make
  2. make install
复制代码
就在安装目录得到了整理好的eigen头文件

按照官方文档所述,其实安装起来不用那么麻烦,只要把头文件拷贝到对应目录就可以了。不过我经过实际检测,不行。如果你在cmake阶段选择了mingw编译器,那么生成的头文件是不能给VC调用的,会出错;而且cmake阶段不同编译器的选项也不尽相同,如果是VC编译器,最多只能支持到sse2指令集,sse3、sse4等等是不支持的,如果你想让你的程序支持更新的指令集,那就等着i7自己来做优化吧。(据说i7可以硬件支持指令集转换)

来测试一段代码
  1. #include <iostream>
  2. #include <ctime>
  3. #include <Eigen/Core>
  4. #include <Eigen/Dense>

  5. using namespace std;
  6. using namespace Eigen;

  7. int main()
  8. {
  9.         int size=2048, N=10;
  10.         clock_t start, end;
  11.         MatrixXf A = MatrixXf::Random(size,size);
  12.         MatrixXf B = MatrixXf::Random(size,size);
  13.         MatrixXf Z = MatrixXf::Random(size,size);
  14.         cout <<"start"<<endl;
  15.         start = clock();
  16.         for(int i=0; i<N; ++i)
  17.         {
  18.                 Z = A*B;  //  or Z = A+B+C ... etc
  19.                 cout<<i+1<<endl;
  20.         }
  21.         end = clock();
  22.         cout << "time taken = " << 1.0*(end-start)/CLOCKS_PER_SEC << endl;
  23.         system("pause");
  24.         return(0);
  25. }
复制代码
这段代码先生成3个2k*2k的随机矩阵,然后重复相乘10次,最后看看计算时间如何。
我的测试平台是:
core i3
win7x86没办法,公司的机器,不能自己换64位系统
mingw-4.5.3
优化参数
  1. -O2 -m32 -mmmx -msse -msse2 -msse3 -msse4 -msse4.1 -msse4.2 -fopenmp
复制代码
生成文件482k,实际执行时间在9.6s到13s之间

我还用armadillo配合gotoblas2静态链接做了一个一样的测试,生成文件452k,实际执行时间11s到15s(这只是为了测试,因为动态链接会损失速度的,但是静态链接原则上违反了LGPL,大家发布程序的时候,不要这么干,还是额外提供一个lapack.dll吧)

这个结果让我万分惊讶,反复测试,eigen都比gotoblas要快多于10%,彻底打破了我原本印象中gotoblas王者的形象,现在大家明白我为什么隆重介绍这个新贵了吧。看来法国科学院选择它还是没错的。我也正在考虑放弃armadillo+lapack的组合,采用eigen来继续我的计算工作。

评分

1

查看全部评分

发表于 2011-6-13 01:32:05 | 显示全部楼层 来自 浙江杭州
Simdroid开发平台
好东西啊

继续发吧
回复 不支持

使用道具 举报

发表于 2011-6-13 02:57:02 | 显示全部楼层 来自 美国
这帖子应该加分,我正在考虑转eigen,他是个好东西,如果linux上用,效果更出众。
回复 不支持

使用道具 举报

发表于 2011-6-17 22:57:12 | 显示全部楼层 来自 美国
lz 这么好的有价值的问题,为什么不投期刊呢?
可以加更多的分,而且让更多的朋友认识你。
我已经把你的文章推荐给准CTO了。
回复 不支持

使用道具 举报

 楼主| 发表于 2011-10-28 18:11:49 | 显示全部楼层 来自 美国
其实我挺纳闷的,这篇才是系列文章中最好的,价值也是最高的,也许是因为不太实用吧,大家都在琢磨着快点干活,到现在顶这篇文章的最少。

最近有些忙,手头的项目拖延的太厉害了,老板很不满意,时间上少了很多。

而且手头的linux工作站也一直没到,看样子老外是不想让我搞这个了,等我11月份回国,摆脱老外的束缚,才能开始搞。

下一篇准备写OpenFOAM的编译和使用,可能要费些力气,大家敬请期待。
回复 不支持

使用道具 举报

发表于 2012-1-27 12:38:52 | 显示全部楼层 来自 江苏扬州
很好的话题
回复 不支持

使用道具 举报

发表于 2012-4-16 12:00:42 | 显示全部楼层 来自 北京
顶楼主啊,大神
回复 不支持

使用道具 举报

发表于 2013-7-25 07:11:56 | 显示全部楼层 来自 湖南衡阳
很好的推荐,Eigen!不过它能联合CUDA做么?
回复 不支持

使用道具 举报

发表于 2013-12-6 15:04:33 | 显示全部楼层 来自 陕西西安
楼主厉害啊!
回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-4-19 05:24 , Processed in 0.043895 second(s), 18 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表