fouvy
fouvy
Fouvy's Notes
54 posts
物理,数学,计算机,金融
Don't wanna be here? Send us removal request.
fouvy · 8 years ago
Text
teamviewer error rollback framework could not be initialized
背景:
  teamviewer 是一个很流行的穿透复杂网络的远程登录软件。使用的用户群比较庞大。
问题:
  teamviewer 最新的版本是 teamviewer 12,低的版本不能直接登录高版本的teamviewer,这个时候就涉及到升级软件了。再软件卸载后重新安装高版本的过程过程中,如果你卸载的时候选择了保存用户设置数据,那么在安装高版本的时候,就涉及到数据rollback的操作了。。。一般情况报下面这个错误的时候:
error, rollback framework could not be initialized
解决方法:
  网上很多的解决方法是,右击使用管理员的权限重新运行,其实这个方法,不一定全部有效,因为数据的rollback不能定能成功,有一种最简单的方法是:
删除旧版本的用户数据,假设你的用户名是administrator,
那么旧版本的数据就是下面这三个文件夹了:
C:\Users\Administrator\AppData\Local\TeamViewer
C:\Users\Administrator\AppData\Local\Temp\TeamViewer
C:\Users\Administrator\AppData\Roaming\TeamViewer
还有一个旧版本的安装路径假设默认安装的话位置就是下面这个:
C:\Program Files (x86)\TeamViewer
把这上面的4个路径文件夹删掉,那么重新安装teamviewer,应该就可以成功了(这个时候可以不用管理员权限运行,也是可以正确安装的)。
0 notes
fouvy · 11 years ago
Text
MongoMatlabDriver无法使用域名连接数据库问题
前言:
Mongodb是一个比较流行的键值内存数据库,应用的范围比较广。接口也比较广泛。当然MATLAB下面的接口也是有的,地址在这边
这个接口其实是将C的Mongodb接口改造成可被MATLAB直接loadlibrary进来的C接口,然后再封装一层面向对象的m class文件的mongo接口。
问题描述:
从目前接触上面看,这个接口依然不是很完善。默认的编辑选项中不能使用域名进行连接数据库,只能使用ip地址进行连接。实际上面底层的C库里面已经考虑了使用域名进行连接数据库问题。只不过作者编译的时候面有考虑这个需求问题。
解决方法:
在MongoMatlabDriver项目属性中,命令行,添加下列指令定义
/D _MONGO_USE_GETADDRINFO 
重新编译MongoMatlabDriver.dll 覆盖掉m文件目录下面的同名文件,就可以解决了无法使用域名连接数据库的问题。
Tumblr media
1 note · View note
fouvy · 11 years ago
Text
MATLAB command window窗口与mex编程程序交互
背景:
我们在进行matlab运算的时候,经常会碰到比较长得计算程序,如果程序是一个m程序的话,我们可以简单的进行ctrl+c停止当前正在运算的程序。如果是mex编程的程序的话,这个方法是不行的。
而MATLAB在开启java虚拟机的情况下,他的command window窗口与正常的c++编程的console程序的命令行程序窗口是有区别的。
在正常的console程序中,你可以在主线程中使用getch之类的等待按键的输入,目标按键出来之后,我们判断按键,就可以进行相应的计算线程的停止和主线程的退出工作。而在MATLAB的command window窗口中运行的程序,这种方法就是不行。
本文通过操作windows的api接口,来达到这种业务需求。
环境:
windows, matlab command window
正文:
主该程序如下面所示:
#include "mex.h" #include <Windows.h> void waitKb(void) {     mexPrintf("按组合键'左Ctrl+c'退出mex文件…");     mexEvalString("drawnow");     while(true)     {         Sleep(200);         if( GetAsyncKeyState(VK_CONTROL) < 0 && GetAsyncKeyState(0x43) < 0)         {             mexPrintf("\n==========退出mex文件==========\n");             break;         }     } } void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[]) {     /*     这里进入计算线程     */     waitKb();     /*     这里停止计算线程     */ }
保存在MATLAB工作目录testKb.cpp文件中,在command窗口输入指令
mex testKb.cpp
(备注:如果你使用的MATLAB默认自带的lcc编译器,请把上面的中文注释都删除掉。lcc不支持中文注释。网站上面发现引号”一直是中文的引号,自己复制过去记得改成英文的引号。)
运行程序:
testKb
消息如下:
按组合键"左Ctrl+c"退出mex文件... ==========退出mex文件==========
拓展:
这个指令是在全局范围内有效的,所以建议绑定一些不常用的组合键。所有按键代码参见这里 。
主线程一直在轮询这个组合键,如果你组合键按的过快的时候,还会有无效的情况。如果你还有比较好的解决方案,可以在下面留言告诉我
对于直接操作win的api可以弥补比较多的MATLAB上面的问题。
0 notes
fouvy · 12 years ago
Text
MATLAB在ubuntu 12.04下配置mex setup编译器
背景:
ubuntu 12.04下面默认的gcc编译器是4.6.3,而matlab 2011b(或者接近的几个版本)的gcc的编译器要求是版本4.3.* 或者如果你不是2011b版本,而是其它的版本,如果和系统自带的gcc的编译器不一样的话一般都要涉及到自己再装一个MATLAB可以支持的编译器.其实原理都是类似的.
本文以 MATLAB 2011B, ubuntu 12.04, gcc 4.3.4为范例,写mex编译器的安装.
首先,我们要按照相应版本的编译器.ubuntu 上面安装gcc的编译器方式,见本博客的另外一篇博文:地址点此:<ubuntu 12.04 gcc 4.3.4 编译>
按照上面的链接提示安装好gcc  4.3.4之后,回来,开始准备配置mexopt.sh
在matlab command窗口中运行:
mex -setup
会显示出几个可以识别的编译器.我这边输出的第一个是:
  1: /usr/local/MATLAB/R2011b/bin/mexopts.sh :       Template Options file for building gcc MEX-files
然后,在外部编辑器中,修改这个文件内容
sudo gedit /usr/local/MATLAB/R2011b/bin/mexopts.sh
分别找到下面三个:
CC='gcc'
CXX='g++'
FC='gfortran'
分别将这三行内容改为:
CC='gcc-4.3'
CXX='g++-4.3'
FC='gfortran-4.3'
保存完后,回到matlab的command窗口中,选择这个编译器.然后确认.
确认之后,matlab就会将这个mexopt.sh模版拷贝到~/.matlab/R2011b下面.(其实你上面也不用那边麻烦改mexopts.sh直接在这个目录下面该mexopts.sh也行,只不过,你下次运行mex -setup可能这个文件会被覆盖掉你要自己重新在设定就是了,所以我就一次修改到位了.).
然后就可以正常在MATLAB中编译文件了.
拓展
对于有些版本的matlab,可能存在会跨越不同版本的gcc和gfortran的情况,这个时候,你可以按照<ubuntu 12.04 gcc 4.3.4 编译>中介绍的方法同时按照几个版本的GCC并且软连接新名字(防止编译器冲突),然后再matlab的mexopt.sh中重新设置相应的编译器.
令人高兴的,MATLAB 2013B linux的版本现在自带了lcc编译器了.这样,我们就不用那么麻烦配置gcc编译器.但是鉴于lcc编译器的局限性.如果要自己配置新编译器的话,那么本文依然有很大的参考价值.
0 notes
fouvy · 12 years ago
Text
Mongo数据库配置
环境: ubuntu server 12.04
配置文件:
sudo vim /etc/mongodb.conf
修改数据库文件夹:
dbpath=/var/lib/mongodb
修改log文件夹
logpath=/var/log/mongodb/mongodb.log
设置数据库按数据库名,放入相应的文件夹中
directoryperdb=true
保存/etc/mongodb.conf文件,并退出
数据文件夹权限设置:
sudo chown -R mongodb:mongodb /var/lib/mongodb
然后重启mongodb服务
sudo service mongodb restart
测试服务器
mongo
#好像我服务器上面运行到这个的时候报错:locale::facet::_S_create_c_locale name not valid
运行指令:
export LC_ALL="C"
然后在运行
mongo
发现登录正常.
0 notes
fouvy · 12 years ago
Text
MATLAB 优化加速经验集合
x = 1:1e6; tic;for loop = 1:1e6, try x(loop); end; end;toc; % Elapsed time is 12.632955 seconds.  x_len = length(x);tic;for loop = 1:1e6, if loop<=x_len, x(loop); end; end; toc; %  Elapsed time is 0.493355 seconds.
%%%%%%%%%%%%% Lazy copy 第一个范例,让你更理解这个东西 %%%%
% filename: testc.m
function testc N = 1:1e6; tic; for loop = 1:1e6, calc(N); end;toc; % Elapsed time is 11.801690 seconds. N = 1:1e6; tic; for loop = 1:1e6, calc2(N); end;toc; % Elapsed time is 5.780150 seconds. N = 1:1e6; tic; for loop = 1:1e6, calc3(N); end;toc; % Elapsed time is 6.732207 seconds. function calc(N) N = N(end); function calc2(N) N_len = N(end); function calc3(N) N = N;
% end of testc.m file
%%%%%%%%%%%%% Lazy copy 第二个范例,让你更理解这个东西 %%%%
% filename: testcf.m
function testcf
N = 1:1e6; tic; for loop = 1:1e4, N=calc(N); end;toc;
% Elapsed time is 0.325009 seconds.
N = 1:1e6; tic; for loop = 1:1e4, N=calc2(N); end;toc;
% Elapsed time is 171.412263 seconds.
function N = calc(N)
N(end) = 1;
function result = calc2(N)
result = N;
result(end) = 1;
% end of file: testcf.m
0 notes
fouvy · 12 years ago
Text
MATLAB数据访问方式与速度
0 notes
fouvy · 12 years ago
Text
MATLAB R2013a 评测
呵呵,这个周末Leney不陪我玩,所以就把MATLAB2011B升级到2013A了,从7到8的跨越。很高兴看到MATLAB越来越成熟。这篇博文也是木有单身,就不会出来了。呵呵~
从MATLAB的更新日志中,我来谈谈,MATLAB2013A更新了那些新的功能吧。
从最基本最常用的开始说:
MATLAB工具箱:
1. 桌面:
添加了快捷工具条,这个7系列的,是单独一行,太占用空间了,我平时都把7系列的给关了。。
2. APPS页:
3. 帮助文档:
添加左边停靠的内容标签,呵呵,方便目录访问定位帮助文档的内容。对搜索的关键自动高亮显示,按ECS关闭关键字高亮显示。呵呵我用的时候,发现帮助文档还有多个TAB页显示的帮助文档的功能,这样方便同时查看多个文档并切换,呵呵,以前都是用退格键查看多个文档的。这个功能不错。(在超链接地方右击的时候,有个从新的页TAB打开文档的功能)。帮助内容菜单,可以放大页内查找,查看源码等(右击帮助文档zoom out缩小,zoom in放大,MAC不知道内容菜单功能)。
4. 启动问题:
如果启动的时候,添加了-nojvm指令的话,MATLAB图像句柄的函数将无法使用,比如plot之类的指令就无法使用(待测试,7系列貌似没有这个问题)。
使用-noFigureWindows 启动选项,将去掉MATLAB启动前加载飞屏。以前这个指令是-nosplash就可以去掉启动的时候的飞屏。
语言和编程
说完了8系列的用户体验,接下来是重头戏,呵呵,说的是语言和编程:
1.       MATLAB单元测试模块(待进一步评测)
很多的语言都有提供单元测试的包,呵呵,以前自己写MATLAB程序的话,一般一个一个自己测试,比较少用单元测试的方法去测试所有的功能,呵呵,这种习惯不严谨哈哈。
2.       字符串处理,添加strsplit,分解字符串,分解后的结果放到元胞cell中,默认是以空白字符为分隔。strjoin将元胞中的字符,合并成字符串。呵呵,一对指令,呵呵。之前,处理字符串都直接也是按照矩阵的方法处理了。
3.       函数validateattributes,检查序列的大小size形状shape。
4.       doc和help指令对面向对象class中,事件和枚举的注释显示支持。
5.       去掉对.jar文件中帮助文档的支持,新版的MATLAB帮助文档必须为html。
6.       .NET必须为4.0及以上,当然支持2.0及以上版本,使用NET.isNETSupported检查你电脑上的.NET是否支持MATLAB。(win平台混编使用的,其他平台这个可以无视)
7.       添加新编译器支持,编译MEX文件。新的编译器有:visual c++ 2012, intel c++ xe 2013, intel fortran xe 2013, xcode 4.2 (mac), 不在支持mac平台上面的xcode gcc。具体详细支持的编译器,请到官方网站查询。
8.       面向对象编程中,继承内置类(built-in classes)不在继承下列方法: ones, zeros, true, false, cast.这些子类对应的方法,无法通过obj.fun的语法调用函数,但依然支持fun(obj)的语法调用。(为了兼容考虑。。。唉MATLAB面向对象。。。)
9.       error 和 warining的消息标记更新:如:MATLAB:addtodate:Nargin变更为MATLAB:addtodatemx:Nargin
10.   datenum, datevec, datestr不在要求月份字符长度严格匹配。呵呵,这个不错。
11.   num2str对于超过flintmax(新函数,最大浮点值),使用大于这个数的科学计数法输出。
12.   不要使用classpath.txt修改java静态路径,兼容性考虑,可以使用javaclasspath.txt或者javalibrarypath.txt
13.   createCopy函数修改为copy
14.   hostid函数将要被移除。
数学部分:
1.       新函数:scatteredInterpolant,散点插值,griddedInterpolant,网格点插值
2.       函数:ones, zeros, eye, Inf, NaN, true, false 和cast,支持按类型输出(新语法)。如:p = uint8([1 2]); X = ones(2,3,'like',p); class(X)结果为uint8.
3.       函数:median, mode, prod, cumprod, cumsum, isprime, primes, factor, gcd, lcm, perms, factorial, nextpow2 和 nchoosek,支持整形integer类型数据输入.
4.       airy函数,添加scale选项
5.       TriScatteredInterp类,替换为scatteredInterpolant类
6.       TriRep 类,替换为triangulation
7.       DelaunayTri类,替换为delaunayTriangulation
8.       集合函数修改:unique, union, intersect, setdiff, setxor,和ismember.索引修改为第一个相同的地址,输出索引从行,改为列。使用’legacy’选项,则返回旧的函数行为。ismember函数,对字符串中的空格开始做区分,如,‘word ’与‘word’变成不是同一个元素。
9.       其它函数修改,具体看release note中
图形相关函数
函数gobjects,预分配图形句柄矩阵,以前使用zeros和ones来预分配。。。
函数替换:
DoubleBuffer不再作用
2 notes · View notes
fouvy · 12 years ago
Text
BitNami Redmine Stack
准备:
      软件: bitnami-redmine-2.2.3-0-windows-installer.exe
说明:
BitNami对Redmine做了集成,有subversion, Apache, mysql, php, ruby, rubygem等,一堆redmine安装需要环境.但是,这个软件安装完之后,还需要对apache和svn做配置,才能在redmine中使用版本控制.
操作:
redmine安装目录(我的是D:\BitNami\redmine-2.2.3-0)下:
1.将下来路径加入系统环境path:
D:\BitNami\redmine-2.2.3-0\subversion\bin
2.拷贝文件(在subversion\bin中)到apache2/bin下,文件如下:
intl3_svn.dll libdb48.dll libsvn_delta-1.dll libsvn_fs-1.dll libsvn_subr-1.dll libsvn_repos-1.dll
3.拷贝模块文件(在subversion\bin中)到apache2/modules下,文件如下:
mod_dav_svn.so
mod_authz_svn.so
4.配置Apache2\conf\httpd.conf 文件
#LoadModule dav_module modules/mod_dav.so #LoadModule dav_fs_module modules/mod_dav_fs.so
中的两个#去掉,即让Apache使用这两个模块
在129行(就是modules加载模块的最后面),添加:
LoadModule dav_svn_module modules/mod_dav_svn.so LoadModule authz_svn_module modules/mod_authz_svn.so
在文件的最后面添加:
<Location /svn> DAV svn SVNListParentPath on SVNParentPath D:\svn AuthType Basic AuthName "Subversion repositories" AuthUserFile D:\svn\passwd AuthzSVNAccessFile D:\svn\authz Require valid-user </Location>
上面的conf文件配置完了.
5.svn目录配置:(面中D:\svn就是我们svn服务所有根目录)
新建文件夹:
D:\svn
创建版本库:
在cmd里面运行:
svnadmin create d:\svn\project
将d:\svn\project\conf\passwd和d:\svn\project\conf\authz 复制到D:\svn下
6.passwd配置和authz配置
在cmd中运行(创建用户user以及其密码 到验证文件d:\svn\passwd中)
cd \D D:\BitNami\redmine-2.2.3-0\apache2\bin
htpasswd -c d:\svn\passwd user
输入两次密码确认下.如果你想添加多个账户的话,最好就不要直接输入到D:\svn\passwd中,会覆盖文件的
打开D:\svn\authz 文件最后添加内容(这里面实际是版本库目录访问授权,具体内容请检索下):
[/] * = r user = rw
7.重启apache服务
在开始菜单中,找到redmine manager tool
点击restart all
访问 http://localhost/svn 输入创建的用户和密码,就可以看到D:\svn下面你建立的所有项目了.可以联网后,你就可以在redmine版本库里面设置(需要填入账号才可以访问)
关键点说明:
如果,你在第7步后依然无法启动Apache,这里的主要原因是modules中的 mod_dav_svn.so 和 mod_authz_svn.so 依赖的subversion/bin中的几个动态库无法被apache正确加载导致的.
你可能需要找到你自己那个版本的apache加载svn模块的说明了.
1 note · View note
fouvy · 12 years ago
Text
无线路由密码分析
环境: ubuntu 12.04
软件:airmon-ng (不懂安装请google)
备注:无线路由,是指tp-link之类的所有无线路由器,无线终端是指笔记本网卡或手机网卡之类的连无线路由的东西。
1. 打开mon0(这里是在第六通道上面打开,一般通道是从1-11,这里打开的通道要和我们要分析无线路由的通道必须一致,下面会说明如何知道目标无线路由的通道)
sudo airmon-ng start wlan0 6
2.在mon0上面扫描第6通道的路由(实际上很多通道的路由都可以看到)并将扫描结果保存到psk*.cap文件里面
在终端输入指令:
sudo airodump-ng --channel 6 -w psk mon0
显示信息如下:
Tumblr media
3.T掉路由器20:DC:E6:4C:4F:1E上的00:24:2C:E6:61:7F无线客户端(T掉后客户端会重连,这时候截取登录密码的握手handshake),这个信息可以从上图中获取,上图中的上半部分是所有扫描到的无线路由,随机选择一个第6通道上面的路由器,且能在上图的下半部分看到这个路由器上面有无线客户端连接上的(因为我们mon0是开在第六通道的,这样为下面这条指令,T掉这个通道上面的无线客户端作准备。只有这个无线路由器有无线客户端连接上,我们才能T的了客户端并截取到handshake,没有无线客户端连接,你哪里去截取握手。。。)
重新开一个终端,输入指令: sudo aireplay-ng -0 1 -a 20:DC:E6:4C:4F:1E -c 00:24:2C:E6:61:7F mon0
大概看到的图如又上角上面get one handshake字样,表明截取到握手(注:我的网卡驱动由于内核升级导致没安装好,所以这里一直显示我的网卡是在fixed channel mon0 -1通道,实际上我第一条指令是让我的mon0在地6通道上开启的sudo airmon-ng start wlan0 6,以前出现这种情况的时候直接在桌面无线网卡点击我们要分析的无线路由点击一下,随便输入一个密码连接一下这个路由,就可以正确切换回这个通道,这次我试的时候,发现依然无法切回那个通道,没心情重新安装无线网卡驱动。。。)
4.暴力破解路由器20:DC:E6:4C:4F:1E截取的handshake握手信息,使用的字典为wpapassword.txt。如果你自己没有字典的话,google一下中国人无线路由字典。
重新开一个终端,输入指令:
sudo aircrack-ng -w wpapassword.txt -b 20:DC:E6:4C:4F:1E psk*.cap
等待暴力破解结果。。。这种方法可以破解wep和wpa等协议无线路由。
5.关闭mon0扫描
sudo airmon-ng stop mon0
0 notes
fouvy · 12 years ago
Link
0 notes
fouvy · 13 years ago
Link
#R
0 notes
fouvy · 13 years ago
Text
ubuntu eclipse pydev 配置
ubuntu 12.04
准备:
eclipse 4.2.1
下载地址:http://www.eclipse.org/downloads/
下载经典版或什么语言版本随你。
JDK 7 (Java platform)
下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html
选择 第一个 Java platform. 进去后,点击同意liscense。下载:jdk-7u10-linux-i586.tar.gz
pydev 2.7.1
下载地址:http://sourceforge.net/projects/pydev/files/
JDK 7
1、解压文件 $ sudo mkdir /usr/lib/jvm $ sudo mv jdk-7u4-linux-i586.tar.gz /usr/lib/jvm/
$ cd /usr/lib/jvm/ $ sudo tar -zxvf jdk-7u4-linux-i586.tar.gz $ rm ./jdk-7u4-linux-i586.tar.gz
2、配置
$ sudo gedit /etc/environment
在environment中修改PATH,追加JDK路径,添加CLASSPATH与JAVA_HOME后如下: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/lib/jvm/jdk1.7.0_04/bin" CLASSPATH="/usr/lib/jvm/jdk1.7.0_04/lib" JAVA_HOME="/usr/lib/jvm/jdk1.7.0_04"
然后就是要告诉系统,我们使用的sun的JDK,而非OpenJDK了:
$ sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk1.7.0_04/bin/java 300 $ sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk1.7.0_04/bin/javac 300 $ sudo update-alternatives --config java 有 2 个候选项可用于替换 java (提供 /usr/bin/java)。 选择    路径                                       优先级  状态 ------------------------------------------------------------ * 0      /usr/lib/jvm/java-6-openjdk/jre/bin/java   1061   自动模式   1      /usr/lib/jvm/java-6-openjdk/jre/bin/java   1061   手动模式   2      /usr/lib/jvm/jdk1.7.0_04/bin/java             300     手动模式 要维持当前值[*]请按回车键,或者键入选择的编号:2 如上所示,这样就设置好了要使用的java了。
eclipse
1、解压文件 $ sudo mv eclipse-cpp-juno-M7-linux-gtk.tar.gz /usr/lib/ $ cd /usr/lib/ $ sudo tar -zxvf eclipse-cpp-juno-M7-linux-gtk.tar.gz $ sudo rm eclipse-cpp-juno-M7-linux-gtk.tar.gz
$ cd /usr/lib/
$ sudo chmod -R 777 eclipse # 修改权限 2、创建启动快捷方式 $ sudo gedit /usr/share/applications/eclipse.desktop 内容如下: [Desktop Entry] Type=Application Name=Eclipse Comment=Eclipse Integrated Development Environment Icon=/usr/lib/eclipse/icon.xpm Exec=/usr/lib/eclipse/eclipse Terminal=false Categories=Development;IDE;Java;
pydev
$ sudo mv pydev2.7.1.tar.gz /usr/lib/eclipse
$ cd /usr/lib/eclipse
$ sudo tar -zxvf pydev2.7.1.tar.gz
在菜单中启动eclipse, 然后就可以在windows>preference 里面看到pydev。点击interperter python. auto config 自动配置安装好的python。
对于注释中的中文,会导致py程序无法运行。
解决方法:
在windows>preference>pydev>editor>templates 中 empty 那个module模板修改为:
#!/usr/bin/python # -*- coding:utf-8 -*- """ Created on ${date} @author: ${user} """ ${cursor}
0 notes
fouvy · 13 years ago
Link
0 notes
fouvy · 13 years ago
Link
0 notes
fouvy · 13 years ago
Text
MATLAB效率分析(转)
MATLAB 效率再议
于MATLAB的效率问题,很多文章,包括我之前写的一些,主要集中在使用向量化以及相关的问题上。但是,最近我在实验时对代码进行profile的过程 中,发现在新版本的MATLAB下,for-loop已经得到了极大优化,而效率的瓶颈更多是在函数调用和索引访问的过程中。
由于MATLAB特有的解释过程,不同方式的函数调用和元素索引,其效率差别巨大。不恰当的使用方式可能在本来不起眼的地方带来严重的开销,甚至可能使你的代码的运行时间增加上千倍(这就不是多买几台服务器或者增加计算节点能解决的了,呵呵)。
下面通过一些简单例子说明问题。(实验选在装有Windows Vista的一台普通的台式机(Core2 Duo 2.33GHz + 4GB Ram)进行,相比于计算集群, 这可能和大部分朋友的环境更相似一些。实验过程是对某一个过程实施多次的整体进行计时,然后得到每次过程的平均时间,以减少计时误差带来的影响。多次实 验,在均值附近正负20%的范围内的置信度高于95%。为了避免算上首次运行时花在预编译上的时间,在开始计时前都进行充分的“热身”运行。)
函数调用的效率
一个非常简单的例子,把向量中每个元素加1。(当然这个例子根本不需要调函数,但是,用它主要是为了减少函数执行本身的时间,突出函数解析和调用的过程。)
作为baseline,先看看最直接的实现
% input u: u is a 1000000 x 1 vector v = u + 1;
这个过程平均需要0.00105 sec。而使用长期被要求尽量避免的for-loop
n = numel(u); % v = zeros(n, 1) has been pre-allocated. for i = 1 : n v(i) = u(i) + 1; end
所需的平均时间大概是0.00110 sec。从统计意义上说,和vectorization已经没有显著差别。无论是for-loop或者vectorization,每秒平均进行约10亿次“索引-读取-加法-写入”的过程,计算资源应该得到了比较充分的利用。
要是这个过程使用了函数调用呢?MATLAB里面支持很多种函数调用方式,主要的有m-function, function handle, anonymous function, inline, 和feval,而feval的主参数可以是字符串名字,function handle, anonymous function或者inline。
用m-function,就是专门定义一个函数
function y = fm(x) y = x + 1;
在调用时
for i = 1 : n v(i) = fm(u(i)); end
function handle就是用@来把一个function赋到一个变量上,类似于C/C++的函数指针,或者C#里面的delegate的作用
fh = @fm; for i = 1 : n v(i) = fh(u(i)); end
anonymous function是一种便捷的语法来构造简单的函数,类似于LISP, Python的lambda表达式
fa = @(x) x + 1; for i = 1 : n v(i) = fa(u(i)); end
inline function是一种传统的通过表达式字符串构造函数的过程
fi = inline('x + 1', 'x'); for i = 1 : n v(i) = fi(u(i)); end
feval的好处在于可以以字符串方式指定名字来调用函数,当然它也可以接受别的参数。
v(i) = feval_r('fm', u(i)); v(i) = feval_r(fh, u(i)); v(i) = feval_r(fa, u(i));
对于100万次调用(包含for-loop本身的开销,函数解析(resolution),压栈,执行加法,退栈,把返回值赋给接收变量),不同的方式的时间差别很大:
m-function                 0.385 sec
function handle          0.615 sec
anonymous function  0.635 sec
inline function           166.00 sec
feval_r('fm', u(i))         8.328 sec
feval_r(fh, u(i))            0.618 sec
feval_r(fa, u(i))            0.652 sec
feval_r(@fm, u(i))        2.788 sec
feval_r(@fa, u(i))         34.689 sec
从这里面,我们可以看到几个有意思的现象:
首先,调用自定义函数的开销远远高于一个简单的计算过程。直接写 u(i) = v(i) + 1 只需要 0.0011 秒左右,而写u(i) = fm(v(i)) 则需要0.385秒,时间多了几百倍,而它们干的是同一件事情。这说明了,函数调用的开销远远大于for-loop自己的开销和简单计算过程——在不同情况可能有点差别,一般而言,一次普通的函数调用花费的时间相当于进行了几百次到一两千次双精度浮点加法。
使用function handle和anonymous function的开销比使用普通的m-函数要高一些。这可能是由于涉及到句柄解析的时间,而普通的函数在第一次运行前已经在内存中进行预编译。
inline function的运行时间则令人难以接受了,竟然需要一百多秒(是普通函数调用的四百多倍,是直接计算的十几万倍)。这是因为matlab是在每次运行时临时对字符串表达式(或者它的某种不太高效的内部表达)进行parse。
feval_r(fh, u(i))和fh(u(i)),feval_r(fa, u(i))和fa(u(i))的运行时间很接近,表明feval在接受句柄为主参数时本身开销很小。但是,surprising的是
for i = 1 : n v(i) = feval_r(@fm, u(i)); end 比起 fh = @fm; for i = 1 : n v(i) = feval_r(fh, u(i)); end 慢了4.5倍 (前者0.618秒,后者2.788秒)。
for i = 1 : n v(i) = feval_r(@(x) x + 1, u(i)); end 比起 fa = @(x) x + 1; for i = 1 : n v(i) = feval_r(fa, u(i)); end 竟然慢了53倍(前者0.652秒,后者34.689秒)。
由于在MATLAB的内部实现中,function handle的解析是在赋值过程中进行的,所以预先用一个变量把句柄接下,其效果就是预先完成了句柄解析,而如果直接把@fm或者@(x) x + 1写在参数列上,虽然写法简洁一些,但是解析过程是把参数被赋值到所调函数的局部变量时才进行,每调用一次解析一次,造成了巨大的开销。
feval使用字符串作为函数名字时,所耗时间比传入句柄大,因为这涉及到对函数进行搜索的时间(当然这个搜索是在一个索引好的cache里面进行(除了第一次),而不是在所有path指定的路径中搜索。)
在2007年以后,MATLAB推出了arrayfun函数,上面的for-loop可以写为
v = arrayfun(fh, u)
这平均需要4.48 sec,这比起for-loop(需时0.615 sec)还慢了7倍多。这个看上去“消除了for-loop"的函数,由于其内部设计的原因,未必能带来效率上的正效果。
元素和域的访问
除了函数调用,数据的访问方式对于效率也有很大影响。MATLAB主要支持下面一些形式的访问:
array-index A(i): 
cell-index: C{i}; 
struct field: S.fieldname
struct field (dynamic): S.('fieldname')
这里主要探索单个元素或者域的访问(当然,MATLAB也支持对于子数组的非常灵活整体索引)。
对于一百万次访问的平均时间
A(i) for a numeric array                    0.0052 sec
C{i} for a cell array                           0.2568 sec
struct field                                       0.0045 sec
struct field (with dynamic name)     1.0394 sec
这是一份在我笔记本上面测试的结果:
A=[1;2];C={1,2};S=struct('f',{1,2});S2.f=1; tic;for loop=1:1e6, A(1);end,toc; % Elapsed time is 0.262127 seconds. tic;for loop=1:1e6, C{1};end,toc; % Elapsed time is 1.253075 seconds. tic;for loop=1:1e6, S(1).f;end,toc; % Elapsed time is 1.251972 seconds. tic;for loop=1:1e6, S2.f;end,toc; % Elapsed time is 10.528915 seconds. tic;for loop=1:1e6, S2(1).f;end,toc; % Elapsed time is 1.382576 seconds.
我们可以看到MATLAB对于单个数组元素或者静态的struct field的访问,可以达到不错的速度,在主流台式机约每秒2亿次(连同for-loop的开销)。而cell array的访问则明显缓慢,约每秒400万次(慢了50倍)。MATLAB还支持灵活的使用字符串来指定要访问域的语法(动态名字),但是,是以巨大的开销为代价的,比起静态的访问慢了200倍以上。
关于Object-oriented Programming
MATLAB在新的版本中(尤其是2008版),对于面向对象的编程提供了强大的支持。在2008a中,它对于OO的支持已经不亚于python等的高级 脚本语言。但是,我在实验中看到,虽然在语法上提供了全面的支持,但是matlab里面面向对象的效率很低,开销巨大。这里仅举几个例子。
object中的property的访问速度是3500万次,比struct field慢了6-8倍。MATLAB提供了一种叫做dependent property的属性,非常灵活,但是,效率更低,平均每秒访问速度竟然低至2.6万次(这种速度基本甚至难以用于中小规模的应用中)。
object中method调用的效率也明显低于普通函数的调用,对于instance method,每百万次调用,平均需时5.8秒,而对于static method,每百万次调用需时25.8秒。这相当于每次调用都需要临时解析的速度,而matlab的类方法解析的效率目前还明显偏低。
MATLAB中可以通过改写subsref和subsasgn的方法,对于对象的索引和域的访问进行非常灵活的改造,可以通过它创建类似于数组的对象。但 是,一个符合要求的subsref的行为比较复杂。在一个提供了subsref的对象中,大部分行为都需要subsref进行调度,而默认的较优的调度方 式将被掩盖。在一个提供了subsref的类中(使用一种最快捷的实现),object property的平均访问速度竟然降到1万5千次每秒。
建议
根据上面的分析,对于撰写高效MATLAB代码,我有下面一些建议:
虽然for-loop的速度有了很大改善,vectorization(向量化)仍旧是改善效率的重要途径,尤其是在能把运算改写成矩阵乘法的情况下,改善尤为显著。
在不少情况下,for-loop本身已经不构成太大问题,尤其是当循环体本身需要较多的计算的时候。这个时候,改善概率的关键在于改善循环体本身而不是去掉for-loop。
MATLAB的函数调用过程(非built-in function)有显著开销,因此,在效率要求较高的代码中,应该尽可能采用扁平的调用结构,也就是在保持代码清晰和可维护的情况下,尽量直接写表达式和利用built-in function,避免不必要的自定义函数调用过程。在次数很多的循环体内(包括在cellfun, arrayfun等实际上蕴含循环的函数)形成长调用链,会带来很大的开销。
在调用函数时,首选built-in function,然后是普通的m-file函数,然后才是function handle或者anonymous function。在使用function handle或者anonymous function作为参数传递时,如果该函数被调用多次,最好先用一个变量接住,再传入该变量。这样,可以有效避免重复的解析过程。
在可能的情况下,使用numeric array或者struct array,它们的效率大幅度高于cell array(几十倍甚至更多)。对于struct,尽可能使用普通的域(字段,field)访问方式,在非效率关键,执行次数较少,而灵活性要求较高的代码中,可以考虑使用动态名称的域访问。
虽然object-oriented从软件工程的角度更为优胜,而且object的使用很多时候很方便,但是MATLAB目前对于OO的实现效率很低,在效率关键的代码中应该慎用objects。
如果需要设计类,应该尽可能采用普通的property,而避免灵活但是效率很低的dependent property。如非确实必要,避免重载subsref和subsasgn函数,因为这会全面接管对于object的接口调用,往往会带来非常巨大的开销(成千上万倍的减慢),甚至使得本来几乎不是问题的代码成为性能瓶颈。
0 notes
fouvy · 13 years ago
Text
git使用方法手记
1 fork分支同步
原repo: https://github.com/QuantBox/CTP.git
我fork的repo: https://github.com/fouvy/CTP.git
在git clone下来的那个目录,右击调出git bash(windows下面,*nux的话,你直接cd到那个,然后git)
git remote add quantbox https://github.com/QuantBox/CTP.git #(这里注意大小写)
下载原repo内容:
git fetch quantbox
合并到我本地的fork repo的主分支上来
git merge quantbox/master
更新我在github上面fork的repo的内容
git push
说明:
如果使用git gui的话,操作也是非常方便的.
0 notes