马上注册,结交更多数据大咖,获取更多知识干货,轻松玩转大数据
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
从本篇文章开始,本人将深入挖掘SAP HANA与R语言整合的具体原理,之所以选择这个主题,很大程度上是因为从SAP D-code大会回来之后,发现有很多相关的应用,尤其是数据分析及预测任务应用到了R, 所以想深入研究一下背后的原理.所以这个系列的文章要求读者了解R语言,并且尝试过与SAP HANA进行整合.相关的文档可以参考https://help.sap.com/hana/SAP_HANA_R_Integration_Guide_en.pdf, 另外可以参考本人的令一篇文章, http://scn.sap.com/community/chinese/hana/blog/2014/02/14/r%E8%AF%AD%E8%A8%80%E5%8C%85%E5%AE%89%E8%A3%85%E5%B9%B6%E5%AE%…
通过这个系列的文章,将向大家揭示SAP HANA与R之间的一个双向数据流的具体步骤, 这样在SAP HANA中使用R语言编写与运行存储过程的时候,理解其中的原理, 将有助于编写的存储过程更加高效, 出现问题的时候也知道该如何去分析原因,查看监控日志,对于有更高需要的用户,甚至可以把R语言整合到你的任何应用中去(当然前提是你的应用中支持TCP/IP通信).
(一) 嵌入式R语言执行环境
在本篇文章中,将介绍一些嵌入式R语言的基础,后续文章再继续揭秘SAP HANA是如何执行R代码的.
SAP HANA能够与R语言整合,在很大程度是因为R语言本身支持一个嵌入式的运行环境.也就是说,你可以把R代码嵌入到C代码中去执行.这当然依赖于R语言在安装的时候安装的一些库.
在R语言的安装目录下(本机:/usr/local/lib64/R),有些头文件,提供了一些函数的原型,还有一个libR.so文件,这是R语言库的动态链接库. 有了这些文件的支持,就可以在C语言中直接嵌入R语言代码了,下面以例子来说明.
- #include <stdio.h>
- #include "Rembedded.h" //包含头文件
- #include "Rdefines.h"
- int main(){
- char *argv[] = {
- "REmbeddedPostgres", "--gui=none", "--silent" //参数
- };
- int argc = sizeof(argv)/sizeof(argv[0]);
- Rf_initEmbeddedR(argc, argv);
- SEXP e;
- SEXP fun;
- SEXP arg;
- int i;
- fun = Rf_findFun(Rf_install("print"), R_GlobalEnv);
- PROTECT(fun);
- arg = NEW_INTEGER(10);
- for(i = 0; i < GET_LENGTH(arg); i++)
- INTEGER_DATA(arg) = i + 1;
- PROTECT(arg);
- e= allocVector(LANGSXP, 2);
- PROTECT(e);
- SETCAR(e, fun);
- SETCAR(CDR(e), arg);
- /* Evaluate the call to the R function.Ignore the return value. */
- eval(e, R_GlobalEnv);
- UNPROTECT(3);
- return 0;
- }
这段代码不是太看好,主要是一些R语言内核定义的一些函数与宏. 主要的过程涉及到调用Rf_initEmbeddedR(argc, argv),初使化一个嵌入式的运行环境,SEXP是一个指针,指向R语言内部的一些数据结构(相关的结构及更多的函数参考R语言源代码R-2.15.0/src/main),然后安义了一个arg数组,初始化为1到10,最后安装了一个print函数,最后调用eval函数来执行R代码. 我们编译一下上面的代码: gcc embed.c -I/usr/local/lib64/R/include -L/usr/local/lib64/R/lib -lR -I参数指定头文件件路径,-L参数指定动态链接库路径,-lR指定链接libR.so这个库文件.
可以看出,这个结果和R语言的运行结果很相似. 由此作为启发,基于嵌入式的R语言运行环境,我们可以自己建立一个R语言的服务器,作为一个TCP/IP的服务器端,接受客户端通过TCP/IP发过来的请求,然后在服务器端执行R代码,再把执行结果返回给客户端. 这便是Rserve这个扩展包的开发初衷. 以上便是SAP HANA与R语言能够整合在一起的一个基础.
(二) Rserve介绍
有了以上的基础, Rserve在2003年10月份的时候就诞生了,到2013年最新发布的Rserve 1.7-3,差不多刚好10年的时间.作者是Simon Urbanek ,现在是AT&T labs的一名研究员,主要做统计相关的一些研究工作,更多介绍见http://simon.urbanek.info/. 有关Rserve的更多信息请参考http://www.rforge.net/Rserve/, 同时该网站提供Rserve相关的服务器端与客户端下载.服务器端 由纯C语言实现, 用来接受客户的请求,数据,进行计算,然后把结果返回给客户端. 客户端提供C++与java还有php的版本. 值得一提的是,作者发布的C++接口只是提供了最基本的功能,还并不完善,用作者自己的话说, “This C++ interface is experimental and does not come in form of a library,”也就是说只是实验性质的,而且作者本人也不用这个C++的接口, 而且只支持R中最基本的比如lists,vectors,doubles这些数据类型,对于其他的一些类型如果需要还得自己实现, “Look at the sources to see how to implement other types if necessary”
在SAP HANA的R客户端中,也是用C++进行实现的,不过这个实现比作者自己提供的那个C++接口要复杂得多. 当然,理论上,只要有TCP/IP协议的支持,你可以用任何语言去实现自己的Client.
(三) 面向消息的通信协议QAP1 Rserve跟客户端的通信协议采用QAP1(quad attributes protocol v1). 基于这种面向消息的协议, 客户端首先发送一个消息,然后等待接受服务器端的响应消息. 消息中必须包含具体的动作,及相关的一些附属数据信息. 服务器的响应消息包含响应代码及结果数据. 每个消息都包含一个消息头部分与数据部分. 每个消息头大小为16个byte. 消息头的结构如下:
Offset type meaning [0] (int) 指定请求或者响应的类型 [4] (int) 指定消息的长度(0到31bit) [8] (int) 指定数据部分的偏移量 [12] (int) 指定消息的长度(32到63bit)
消息的数据部分可以包含一些附加参数, 比如DT_INT,DT_STRING等类型的参数.具体参考Rsrv.h 当前Rserve支持的一些命令如下: command parameters | response data
CMD_login DT_STRING | - CMD_voidEval DT_STRING | - CMD_eval DT_STRING or | DT_SEXP DT_SEXP CMD_shutdown [DT_STRING] | - CMD_openFile DT_STRING | - CMD_createFile DT_STRING | - CMD_closeFile - | - CMD_readFile [DT_INT] | DT_BYTESTREAM CMD_writeFile DT_BYTESTREAM | - CMD_removeFile DT_STRING | - CMD_setSEXP DT_STRING, | - DT_SEXP CMD_assignSEXP DT_STRING, | - DT_SEXP CMD_setBufferSize DT_INT | - CMD_setEncoding DT_STRING | - (since 0.5-3) since 0.6: CMD_ctrlEval DT_STRING | - CMD_ctrlSource DT_STRING | - CMD_ctrlShutdown - | - since 1.7: CMD_switch DT_STRING | - CMD_keyReq DT_STRING | DT_BYTESTREAM CMD_secLogin DT_BYTESTREAM | - CMD_OCcall DT_SEXP | DT_SEXP
实用最多的一个command是CMD_eval. 这个命令的作用就是根据接受到的一符合R语言语法的字符串,对它进行语法解析,然后计算运行,得出结果,然后再发回响应消息.
其实如果能够直接在SAP HANA内部运行R程序,基于嵌入式R,在技术上是可行的也是简单的,而且性能上会更好,但是很遗憾因为开源软件的版权问题不能直接这么做. 本篇文章的介绍先到此结束,在后续的文章中我再介绍Rserve的运行机制及SAP HANA中具体如何与Rserve进行通信的. 了解这些原理,对于优化Rserve,获得更高的性能,是有必要的. 因为Rserve是开源的,如果对底层细节胸有成竹的话,可以自己对Rserve进行改进,达到自己的需求.
|