Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
0 Kudos

      从本篇文章开始,本人将深入挖掘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%A...

       通过这个系列的文章,将向大家揭示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]  = 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介绍

          有了以上的基础, Rserve200310月份的时候就诞生了,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 HANAR客户端中,也是用C++进行实现的,不过这个实现比作者自己提供的那个C++接口要复杂得多. 当然,理论上,只要有TCP/IP协议的支持,你可以用任何语言去实现自己的Client.

() 面向消息的通信协议QAP1

 

       Rserve跟客户端的通信协议采用QAP1(quad attributes protocol v1). 基于这种面向消息的协议, 客户端首先发送一个消息,然后等待接受服务器端的响应消息. 消息中必须包含具体的动作,及相关的一些附属数据信息. 服务器的响应消息包含响应代码及结果数据. 每个消息都包含一个消息头部分与数据部分. 每个消息头大小为16byte. 消息头的结构如下:

                                  Offset                      type                 meaning

                [0]              (int)       指定请求或者响应的类型

                [4]              (int)       指定消息的长度(031bit)

                [8]              (int)       指定数据部分的偏移量

                [12]             (int)       指定消息的长度(3263bit)

       消息的数据部分可以包含一些附加参数, 比如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

        实用最多的一个commandCMD_eval. 这个命令的作用就是根据接受到的一符合R语言语法的字符串,对它进行语法解析,然后计算运行,得出结果,然后再发回响应消息.

        其实如果能够直接在SAP HANA内部运行R程序,基于嵌入式R,在技术上是可行的也是简单的,而且性能上会更好,但是很遗憾因为开源软件的版权问题不能直接这么做.

        本篇文章的介绍先到此结束,在后续的文章中我再介绍Rserve的运行机制及SAP HANA中具体如何与Rserve进行通信的. 了解这些原理,对于优化Rserve,获得更高的性能,是有必要的. 因为Rserve是开源的,如果对底层细节胸有成竹的话,可以自己对Rserve进行改进,达到自己的需求.


  想获取更多SAP HANA学习资料或有任何疑问,请关注新浪微博@HANAGeek!我们欢迎你的加入!

  转载本文章请注明作者和出处http://scn.sap.com/community/chinese/hana/blog/2014/04/13/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3sap-ha...,请勿用于任何商业用途。