Ubuntu下使用icc/ifort/MKL编译R及性能实测

1 基本环境

  • Ubuntu 11.04 32-bit
  • R 32-bit 2.13.0
  • Intel Composer XE 2011.3.174(含icc/ifort/MKL)

MKL(Intel Math Kernel Library), 号称"provides extremely well-tuned BLAS and LAPACK implementations that deliver significant performance leadership over alternative math libraries". 在特定的计算情境下会带来一定的性能提升. 记得哪里看到过Revolution R和MATLAB就有用到MKL. 这里尝试用Intel提供的C和Fortran编译器结合其MKL库编译R, 以期尽量发挥现有硬件的性能. Intel的Composer XE中自带了MKL, 而且icc/ifort基本是傻瓜化安装, 这里不再赘述.

2 编译过程

假设icc/ifort/MKL安装在默认的 /opt/intel/composerxe-2011.3.174/ 目录下.

通常我们会这样简单编译安装:

wget http://ftp.ctex.org/mirrors/CRAN/src/base/R-2/R-2.13.0.tar.gz
tar -xf R-2.13.0.tar.gz
cd R-2.13.0
./configure
make
sudo make install

这次具体指定一下参数就好了.

继续阅读

R之不务正业 - Chromium Updater

r_chromium_logo

Chromium是Google Chrome开发版的名称, 这东西每天发布20来个更新版本是正常现象. 故有"好事者"写了名为Nightly Chrome Updater的Chrome扩展, 更有甚者, 制作了专用GUI工具来检查和下载更新 ... 不过 .. 用R中的基础函数写一段脚本来做这个简单工作是再好不过了. 想想每次开R时加载一段脚本自动更新Chromium, 有益身心健康 ...

trunkURL = 
"http://build.chromium.org/f/chromium/snapshots/chromium-rel-xp/"
tmpDir = getwd()
appDir = gsub('Application Data', 
	'Local Settings/Application Data/Chromium/Application/', 
	Sys.getenv("APPDATA"))
rmDir = list.files(path = appDir, pattern = "\b\d")
download.file(paste(trunkURL, "LATEST", sep = ''), 
		paste(tmpDir, "/LATEST", sep = ''), 
		quiet = TRUE)
versionNum = readLines(
		paste(tmpDir, "/LATEST", sep = ''), 
		warn = FALSE)
unlink(paste(tmpDir, "/LATEST", sep = ''))
download.file(
		paste(trunkURL, versionNum, 
		"/mini_installer.exe", sep = ''), 
		paste(tmpDir, "/mini_installer.exe", sep = ''), 
		mode = "wb")
shell.exec(paste(tmpDir, 
		"/mini_installer.exe", sep = ''))
Sys.sleep(30)
try(unlink(paste(appDir, rmDir, 
		sep = ''), recursive = TRUE))
try(unlink(paste(tmpDir, 
		"/mini_installer.exe", sep = '')))

这个mini_installer.exe事实上是一个自解压静默安装程序, 用7-Zip可以打开瞧瞧. 但它不会清理原有程序所在目录, 所以清理临时文件和原有程序目录的任务正好就交由脚本完成了. R中的DLL.version()函数要是支持提取DLL中指定字段的信息就好了, 因为Chromium的版本信息是写在chrome.dll中的, 那样就可以先比较当前版本号再判断是否有必要更新了, 残念 ......

写完了发现毫无技术含量, 而且是简单到令人发指的程度了 ... 当然, 我们可以经过深思熟虑往里加if并包装成函数 ... 改改还可以跨平台, 不过我只会在Win下用, 因为Debian什么的用apt三两句就搞定, 而其他*nix-like系统写shell脚本最简单.

再做个GUI程序就理想了.

The Story of R and OAuth

r_oauth_logo

OAuth以降, 第三方client需要在授权时接触明文密码的问题解决了. Twitter在今年8月开始强制推行OAuth授权方式. 对此, R中的twitteR包作者Jeff Gentry却在最新的文档中叫苦不迭:

The old Twitter authentication mechanism is being removed in August 2010 in favor of OAuth. As of this writing there is not an OAuth solution for R, so unless someone (or myself) writes such a beast you will not be able to access any authenticated aspects of Twitter. Many functions that you might be familiar with using will no longer work properly, if at all. These have been set to be defunct.
Also not that it is not simply a matter of having an OAuth interface, but also that Twitter's usage of OAuth is very tied to having stable applications as opposed to scripts being written. There are currently various potential workarounds for this that I'm looking into.

看来自从授权方式改为OAuth之后, 大部分写好的功能都极其华丽丽的失效了. 我没有读过OAuth规范, 不过个人认为, 实现OAuth的一个难点在于需要用户在浏览器中进行一步通过授权的操作. 而其他的token生成, 取回token之类的, 对于开发者都是些简单问题而已. Stack Overflow上就曾经有人问在R中怎么进行OAuth授权的问题, 有人说不妨尝试用Quick and Dirty的方式, 其实, 这个答案也很Quick and Dirty啊.

从这个角度出发, 就我的感觉, 从技术上讲, client开发大概可以分为以下3种情况:

  1. Web开发, 如php. 客户端本身就是在浏览器里干活, 很容易实现, 且可以借鉴现成代码;
  2. 编译型语言的桌面开发, 如C. 可以通过在客户端内调用浏览器组件实现认证, 对用户很友好, 且有现成的lib, 实现较容易;
  3. 脚本语言的桌面开发, 如Python和R. 除非写很suck的GUI client, 否则基本不可能在客户端内调用浏览器. 这时就可以分出两种处理方式:
    • 打开(或让用户手动打开)浏览器, 然后授权获取token, 让用户手动粘贴过来, 整个过称很怪异, 很不友好;
    • 祭出神器cURL(libcurl)处理.

这里忽略情况1和情况2, 专注于情况3. 情况3的第一种处理方式非常不友好, 但是这也是一些现有示例的处理方式, 如Python. -_-!! 而第二种处理方式的技术难度非常高, 因为天知道那个授权页面是不是用了一些cURL容易处理的方式写成的, 比如授权页面里包含了一些ajax或是其他的什么东西, 完全依赖于开放API的网站有没有考虑到这一点了. 当然, 这是我的个人看法, 这些问题对于大牛也许都不是问题吧. 当然, 如果能使用第二种处理方式, 是再好不过了, 简直完全不亚于情况2. 不过我想没有真正的最终用户去用这种纯命令行的client, 基本都是开发人员用. 以上那些所谓的友好不友好的标准, 也都是针对会用哪一种client做事的用户群而言的, 莫要细究.

回到开始的TwitteR话题. 一位日本人在最近写了一些关于在R中怎么进行OAuth授权的东西, 当然, 仅仅是针对Twitter的. 他的Slides在这里可以看到. 相关的R代码在GitHub上. 由于我没有研究过这个网站的API, 所以不知道他最后实现的是不是我所谓的第2种方式, 单纯从代码上看起来还是比较像的. 希望Jeff看到这些能够有动力把包里的大部分函数更新一下 ...

同时也期待Duncan Temple Lang这些牛人们早日给R做一个标准的OAuth包吧.

R-Forge用户手册 中文版

r-forge-manual
R-Forge是提供给R社区的一项开源社区服务, 它拥有SVN和一系列基于Web页面的管理功能. 使用R-Forge, 可以很方便地维护R包. 并且, 通过R-Forge质量管理系统测试的R包, 能够以一种标准化的方式直接发布到CRAN.

这里是我制作的《R-Forge User's Manual》中文版本, 只有短短几页, 简单看过之后即可上手.

文档来源:
http://r-forge.r-project.org/scm/viewvc.php/doc/Manual/?root=site&pathrev=147

编译说明:
为了使用效果更加稳健的中文字体, 我改造了源文件, 使用XeLaTeX编译. 当然, 你还得有相应的字体.

关于译文:
我不熟悉SVN, 所以可能有些名词译得不对, 希望看出的同学不吝指出, 我会立即修正, 先行谢过.

Download:
[Manual, PDF, 279KB]
[Source, Gzip, 13KB]

逆序字符串的3种R实现

逆序字符串或数字是一个比较simple的问题. 由于数字也可以作为字符串处理, 所以一般处理字符串的方法都可以改造为逆序数字的方法. 这里列出3种在R中思路各异的实现方法.

1. 逆序一个整数, 经典的数学方法:

?View Code RSPLUS
numRev=function(num){
rem=0
while(num>0){
rem = (rem * 10) + (num %% 10)
num = as.integer(num / 10)
}
return(rem)
}

优点是最容易想到. 缺点很明显, 引入while做循环且需计算, 效率过低.

2. 此法可逆序字符串, 简单改造即可逆序数字:

?View Code RSPLUS
x=seq(10001,99999)
x=sapply(strsplit(as.character(x),""), 
         function(i) paste(rev(i),collapse=""))

简单的三步: 拆, 倒, 并. 加上as.integer()就可以逆序数字了. 粗略看了一下, 此法较上法可节约20%左右的时间. 参考了COS原帖. 谢谢谢老大!

3. 此法适于逆序数字, 理论上可以逆序字符串. 实质是把数字当作字符串, 用正则处理, 似乎是perl黑客的风格:

?View Code RSPLUS
x=seq(10001,99999)
x=as.integer(sub( '^([0-9])([0-9])([0-9])([0-9])([0-9])',
                  '\5\4\3\2\1', x))

所需时间几乎仅为上法的10%, 适合处理位数相对固定的大量数字, 位数改变时需修改表达式. 这里参考了StackOverflow上的一个帖子.

需要注意的是, 使用as.integer()时, R将默认吃掉前方的0. 12580将变为8521. 这些方法都是最简单的, 也很方便移植. 如果大家有效率更极致的方法, 欢迎补充.

Mapping CRAN Mirrors using R

CRAN_mirrors_map
昨天突然想看一下怎么用maps包画地图, 就做了一个CRAN镜像的地理位置数据试了一下. 城市地理位置数据主要来自maps包中的数据集world.cities. 画图时用到了maps和tripack这两个包, maps用于呈现地图, 而tripack可以根据给定点坐标计算并绘制Voronoi图/Delaunay三角剖分. 相比主流的C或C++甚至Python下的实现, 在R中做这种事情可以说是简单无比了. 同时也要慨叹R的扩展性是如此之好. 不过目前R中和计算几何相关的包似乎不多, 据我所知还有rcdd(cddlib在R中的接口)和geometry. 比如geometry包, 可以计算n-维上的Delaunay三角形, 等等. 如果某天哪位大牛可以替最强的计算几何算法库CGAL在R中做一个接口就好了.

CRAN_Mirrors_Voronoi

Voronoi Diagram of CRAN Mirrors on World Map [PDF(Vector), 120KB]

CRAN_Mirrors_Delaunay

Delaunay Triangulation of CRAN Mirrors on World Map [PDF(Vector), 120KB]

从图中看, 多数CRAN镜像分布在沿海地区, 内陆较少, 也极不均匀. 西欧密集分布了约30个镜像, 面积是其几倍大小的东侧大片内陆只有寥寥3、4个镜像. 非洲、南美洲的情况大致相同. 北美的镜像分布呈现比较均匀的态势, 至少看上去比较稳定, 不多也不少.

Dataset & R Code [Gzip, 1,932 bytes]

有两个问题是不得不考虑的:

  1. 地球是椭球体, 在球面上绘制Delaunay三角和Voronoi图, 需要通过计算三维空间中的凸包来实现 .. 但考虑到事实上太平洋中间没有CRAN的镜像, 正好十分自然地将现有镜像隔得很远, 就无视这个了 ..
  2. CRAN镜像发挥的影响力与各地光缆铺设情况的关系更紧密, 这时用地理意义上的世界地图就显得略不给力了 .. 使用能够体现网络分布情况的"地图"才是正解.