【转载】关于Mathematica提速的10点技巧
mathematica吧
全部回复
仅看楼主
吧务
level 11
situxuming 楼主
看到有吧友求MMA编程提速技巧,就想到这篇文章了。这篇是Wolfram Blog上的一篇文章http://blog.wolfram.com/2011/12/07/10-tips-for-writing-fast-mathematica-code/,之后在网上看到有人将之翻译过来了,就转载过来给各位吧友看看吧~此翻译文章的原址是http://www.cnblogs.com/mymma/archive/2012/08/27/2659007.html
当人们跟我抱怨说Mathematica不够快时,我一般会叫他们去仔细瞧瞧那些令人恼怒的代码.跑得慢的原因通常不是Mathematica的性能问题,而是使用方式不太合适.我想我应该分享一些我在优化Mathematica代码时使用的技巧.
1.如果可能话,使用机器精度数并尽量提早使用
如我所见,那些漫不经心的程序员所编写的缓慢的代码的一个共同特点是,一下子让Mathematica考虑到了太多的琐事而忽略自己的实际需求.不必要的附加计算是导致代码缓慢的最普遍原因.
大部分的数值计算软件中没有这些附加计算,1/3和0.33333333333333被认为是相等的.这些附加计算在你遇到一些复杂难缠的计算时是很有用的.但是在大部分的计算任务中,浮点运算的机器精度已经足够好,更重要的是,计算速度更快.任何小数位数小于16位的十进制输入都会自动被Mathematica按机器精度处理,所以,如何你的计算原则是速度优先,那么就尽可能使用机器精度的小数而不是精确形式(例如1/3).这里有一个简单的例子说明直接使用浮点数进行机器精度的运算会比先用绝对精确形式计算然后转换为小数的方法快50倍左右.当然,我们这个例子里得到的结果是相同的.
2013年02月28日 03点02分 1
吧务
level 11
situxuming 楼主
这个结果对于符号计算也是成立的.如果你不在乎符号形式的结果和稳定性,那么尽可能早地使用浮点数.例如,在解这个多项式方程之后为系数赋值以避免长达5页的符号形式结果.
但是如果你在解方程之前就赋值,函数Solve会直接使用速度飞快的数值计算方法.
当你对表中的数据进行处理时,一定要保证所用的数据都是浮点小数形式的.某一个数据形式的不同就会导致整个表中的数据用另一种灵巧有余而效率不足的方式存储.
2013年02月28日 03点02分 2
吧务
level 11
situxuming 楼主
2. 学习如何使用Compile…
函数Compile允许你对所编译的函数的参数的类型(实数,整数,复数…)和结构(数值,表,矩阵…)做预先声明.这样做损失了Mathematica语言的灵活性,但是另一方面消除了”如果参数是符号形式的该怎么办?”的焦虑.同时Mathematica也可以优化程序生成在其虚拟机上运行的高速字节码.不是所有的函数都能被编译,过于简单的代码也可能从编译中得不到好处,但是复杂的低级数值运算代码可以得到极大的速度提升.
这里有一个例子:
用Compile代替Function使计算速度提高了80倍.
为了得到更高的性能,我们可以对Compile做进一步的关于并行运算的调整.
喏,在我的双核电脑上,速度比原始代码快乐足足150倍.如果我的CPU有更多核的话速度会更快.
读者们要意识到很多Mathematica函数比如Table,Plot,NIntegrate会自动进行编译,所以再使用Compile也不会看到一点效率上的提高.
2013年02月28日 03点02分 3
吧务
level 11
situxuming 楼主
2.5利用Compile生成C代码.
更进一步,如果你的代码是可编译的话,你可以使用CompilationTarget->”C”选项生成C代码,它会自动调用你的C编译器生成动态链接库(DLL),并链接回Mathematica.这样做会在编译阶段花费更多的时间,但是动态链接库能直接运行在CPU上而不是Mathematica虚拟机,所以速度会更快.
3. 尽可能使用内置函数.
Mathmatica中函数众多.大部分人不会坐下来一个接着一个地学习这些函数.所以当我看到一些人拼命地实现一些特定功能而没意识到Mathematica早就用内置函数实现其功能时也就不感到奇怪了.这样重新造轮子的行为不仅浪费时间,而且我们这些人的工作就是设计做好的算法以应对各种输入并保证效率,所以绝大部分的内置函数是非常快的.
如果你发现你的代码已经很不错了但是好像还欠了点什么,查看一下选项和附加参数;通过它们能获得很多特定的功能和抽象的应用.
有一个这样的例子.比如我想把一个100万个的2阶矩阵转换为100万个一维列表,最容易想到的方法就是使用Map和Flatten的组合.
其实整个任务只要Flatten一个函数就可以做到.找到这个方法有点浪费时间,但这是值得的,整个任务的速度比比你的自己造的轮子快了接近4倍.
谨记在心---自己造轮子之前先去看看帮助.
2013年02月28日 03点02分 4
吧务
level 11
situxuming 楼主
10. 横看成岭侧成峰.
在Mathematica中,完成同一件事总是有很多条途径.编程风格总是跟着问题走,而不必为了迎合单一的编程风格而重新考量问题本身.然而,概念上的简单不总是等同于计算上的高效.有时容易理解的想法会带来很计算上的”无用功”.
预测那种方法更高效一般是很困难的,因为Mathematica会自动地进行特别的优化和采用高效的算法.比如,下面两个例子都能计算阶乘,但是显然第二种方法更加快速.
为什么会这样?对此你可能会有种种猜测:Do循环太慢?赋值浪费时间?或者其它的一些错误?真正的原因是难以预料到的.Times对大数或大整数有一种二进制分离技巧,比递归地参数分离成较小的乘积更快.这两种情况所作的乘积数是一样的,但是后者更少地操作大整数.有很多像这样不为人知的魔法隐藏在Mathematica中,随着版本的更新这种魔法也会越来越多.
当然,最快的方法还是直接使用内置函数:
Mathematica有能力进行卓越性能的计算,也有很高的鲁棒性和精度.虽然这两点一般不能同时拥有.我希望这些技巧能帮助你去达到快速编程,高效计算,和精确结果这三点间的平衡.
2013年02月28日 03点02分 7
level 8
怎么没人顶啊
2013年12月03日 14点12分 8
吧务
level 11
http://www.withparadox2.com/archives/1 这也关于提高效率
2013年12月04日 12点12分 9
链接失效了?
2018年01月23日 07点01分
@Alexander0620 估计是我也打不开 我都不记得是啥了 四年了。。。。
2018年01月23日 14点01分
@wshzh1966 pity
2018年01月24日 06点01分
level 12
太棒了!
2013年12月04日 13点12分 10
level 12
的确很有用,一针见血
2013年12月04日 13点12分 11
level 12
@mm_酱 帮着申精,以后看着方便
2013年12月06日 11点12分 12
好。
2013年12月06日 13点12分
level 9
用64位也勉强算是提速的技巧吧。。。。>_>
2013年12月06日 14点12分 13
吧务
level 11
我也看到一个类似的好帖
http://www.withparadox2.com/archives/38
2014年01月01日 14点01分 14
吧务
level 11
2014年01月01日 14点01分 15
level 13
好东西
2014年01月06日 01点01分 16
level 11
马克!
2014年04月12日 15点04分 17
level 4
感觉很受用,顶!
2014年04月13日 15点04分 18
level 11
顶起!!!
总结的很给力
2014年09月03日 01点09分 20
level 1
mark
2014年09月03日 07点09分 21
level 1
这种帖子不顶怎么行
2014年12月02日 15点12分 22
level 1
问个问题 现在Mathematica并行计算最多能支持多少核
2014年12月18日 10点12分 23
取决于许可证。盗版无限核。
2015年01月03日 08点01分
1 2 尾页