没有合适的资源?快使用搜索试试~ 我知道了~
dotCall64:R包,支持长向量和外部函数接口的增强版
−≥SoftwareX 7(2018)217原始软件出版物dotCall64:一个R包,为支持长向量F. Gerbera,*,K.默辛格河Furrera,ba瑞士苏黎世大学数学系b瑞士苏黎世大学计算科学系ar t i cl e i nf o文章历史记录:2018年1月12日收到2018年6月14日收到修订版,2018年保留字:外部功能接口64位大型数据集a b st ra ctR包dotCall64提供了一个增强版的外部函数接口(FFI),用于从软件环境R中调用编译后的C、C++和Fortran代码。它允许用户在不使用复杂的应用程序编程接口(API)(如R的C API)的情况下集成编译后的代码。此外,dotCall64支持长度大于231的长向量1元素并实现了一种机制,避免不必要的R对象副本。因此,dotCall64有助于使现有的C,C++和Fortran库可用于R,并且对于涉及长向量的应用程序特别有用。版权所有©2018作者.由爱思唯尔公司出版这是CC BY许可下的开放获取文章(http://creativecommons.org/licenses/by/4.0/)中找到。软件元数据当前代码版本v0.9-5.2用于此代码版本的代码/存储库的永久链接https://github.com/ElsevierSoftwareX/SOFTX_2018_56法律代码许可证GPL-3使用git的代码版本控制系统https://git.math.uzh.ch/reinhard.furrer/dotCall64使用R、C、openMP的编译要求、操作环境R(v3.1)如果可用,链接到开发人员文档/手册https://cran.r-project.org/web/packages/dotCall64/dotCall64.pdf支持电子邮件问题florian. math.uzh.ch1. 动机和意义开 源 编 程 语 言 R 是 一 种 流 行 的 统 计 计 算 软 件 环 境(https://www.r-project)。org/)。它的解释特性使R成为广泛应用的方便前端虽然R提供了丰富的基础设施,但使用C、C++或Fortran编写的编译代码扩展R程序可能是有利的[1]。这种扩展的原因是对新的和可信的计算的访问,计算速度的增加,以及对象引用能力[2]。R提供了两种类型的接口来调用编译后的代码[3]。首先,外部函数接口(FFI)提供R函数.C()和.Fortran()。这个接口允许编译后的代码读取和修改原子R向量,这些向量分别公开为相应的C、C++和Fortran类型。因此,不需要对编译后的代码进行R特定的自适应,这有利于通讯作者。电子邮件地址:florian. math.uzh.ch(F. Gerber)。https://doi.org/10.1016/j.softx.2018.06.002嵌入C,C++和Fortran代码,不是专门为R设计的。其次,C/C++代码(MIC)的现代接口以R函数.Call()和.External()为特色。它们允许使用R的C API从C访问、修改和返回R对象[4]。 当C代码专门编写用于R时,这很方便。在这种情况下,C API充当R和C之间的粘合剂,提供一些R功能和在C级别上复制R对象的控制。但是,它需要用户学习C API钢筋混凝特别是,当R接口构建在现有编译代码之上时,这构成了额外的工作。此外,R没有Fortran API,因此,MIC不方便将Fortran代码嵌入R。在这些接口之上,R包可以简化内部将编译代码集成到R中。一个这样的R包是inline [5],它允许用户使用内联编译代码动态定义R函数和S4方法。其他例子是Rcpp [62352-7110/©2018作者。由爱思唯尔公司出版这是CC BY许可下的开放获取文章(http://creativecommons.org/licenses/by/4.0/)。可在ScienceDirect上获得目录列表SoftwareX期刊主页:www.elsevier.com/locate/softx*218F. Gerber等人/SoftwareX 7(2018)217图1.一、 CRAN(https://cran.r-project.org/)上使用外部函数接口(蓝色)和C/C++代码的现代接口(黄色)的R软件包数量表1FFI中的R函数.C()和dotCall64中的.C64()的参数和默认值。.C()的贬值参数标记为.C().C64()参数默认参数默认.NAME.NAME签名......意图空奈克奈克DUP TRUE包装包装编码VERBOSEgetOption(“dotCall64.verbose”)面向C、C++或Fortran代码(截至2018-01-09)。请注意,从1′872 R包使用.Call()1′ 321(70%)链接到Rcpp。(对于颜色参考的解释在此图例中,读者可参考本文的网络版本用C++代码扩展R。与MIC类似,Rcpp包系列旨在使用专门为此目的编写的编译代码扩展R。在本文的其余部分,我们将重点关注在不使用额外的C或C++ API的情况下将编译代码嵌入R的意图。这个任务的自然解决方案似乎是FFI,CRAN上大约40%的包嵌入编译的C,C++或Fortran代码使用该接口(图1)。这样的R包的一个例子是SPArse Matrix包spam [15在这里,FFI中的R函数.Fortran()似乎是合适的。相反,使用MIC也是可能的,但需要添加一个额外的C代码层,用于实现R和编译的Fortran代码。然而,使用FFI也不令人满意,因为它缺乏灵活性和 性 能 , 正 如 它 的 帮 助 页 面 中 所 述 : 后 来 的 接 口 是 “.Call” 和“.External”,它们更灵活,性能更好。FFI缺少的两个功能是:• 一种避免不必要的R对象副本的机制• 支持长向量。前者是FFI性能低于MIC的原因。由于FFI不允许R向量通过引用(不复制)传递到编译代码,因此对于大数据应用来说尤其不切实际FFI缺少的特性促使开发了本文中介绍的R包为了理解将长R向量传递给编译代码的主要困难,应该注意R使用双精度来索引长向量,而编译代码自然使用64位整数(更多细节在补充材料的第S1节中给出因此,将长向量的索引从R传递到编译后的代码涉及到类型转换(类型转换),这是完全自动化的,并通过所提出的接口并行化相反,可以考虑使用R包bit64 [19]提供的64位整数类来避免类型转换。然而,该类不能用于索引长R向量,因此无助于避免强制转换。2. 软件描述R包dotCall64 [20]包含R和C源代码,文档,示例,使用R 包testthat [21]实现的单元测试,以及用于性能测量的R脚本。2.1. 软件功能dotCall64的主要R函数是.C64(),它是FFI的增强替代品,同样易于使用。的语法表2支持.C64()的SIGNATURE参数和相应的C、C++、Fortran和R数据类型。列SignatureC,C++ type Fortran type R type cast‘‘double’’doubledoubleprecisiondouble.C64()类似于函数.C(),两个函数都有共同的参数,如表1所示。参考手册[20]中也给出了更多细节。.C64()所需的参数是:. NAME编译的C、C++函数或Fortran子例程的名称。... 编译后的代码最多可访问65个R向量。SIGNATURE一个字符向量,其长度与编译函数(也称为Fortran子例程)的参数数相同。每个字符串指定一个这样的参数的签名。可接受的签名为表2中给出了与这些规范对应的R、C、C++和Fortran类型。这样,下面使用.C()对编译后的C函数void get_c(doubleinput,int index,double output)的调用就可以被对应的.C64()替换。因此,例如,R>.C(“get_c”,input=as.double(1:10),index=as.integer(9),output=double(1))成为R>.C64(“get_c”, SIGNATURE =c(“double”,“integer”,“double”),input=1:10,index=9,output=0)虽然稍后会给出更详细的代码示例,但这足以突出.C64()的一些功能。首先,.C64()需要额外的参数SIGNATURE来指定编译函数的参数类型。作为回报,它将提供的R向量强制为指定的签名,从而使as.double()和as.integer()语句变得不必要。其次,所有提供的参数都可以是长向量。第三,如果编译函数的参数之一是64位整数(在C 、C++函数的情况下为int64_t ,在Fortran子例程的情况下为integer(kind = 8)类型),则将相应的SIGNATURE参数设置为也就是说,.C64()分别在计算编译代码之前和之后执行必要的双精度转换为64位整数和64位整数转换为双有关R的长向量支持的详细信息,请参见补充材料的第S1节,这解释了为什么需要上述铸件F. Gerber等人/SoftwareX 7(2018)217219.C64()的其他参数如下:INTENT一个字符向量,其长度与编译函数的参数数量相同每个字符串指定一个这样的参数的意图可接受的Intent是NAOK一个逻辑标志,指定R向量是否通过“.”检查缺失值和无限值。PACKAGE一个长度为1的字符向量,将编译函数的搜索路径限制在指定的包内。VERBOSE如果为0(默认值),则不打印警告。如果为1和2,则打印用于调整和调试目的的警告。参数INTENT影响R向量的复制,并且可以被视为.C()的贬值DUP参数的增强版本。默认情况下,所有intent都被设置为“read andwrite”,这意味着编译后的代码将接收到指向“. . 当编译函数读取相应的R向量并修改(写入)它们时,这种行为是可取的对于编译函数的仅读取而未修改的参数,可以将Intent设置为“read”。这样,编译后的代码就接收到指向相应R向量本身的指针。虽然这避免了复制,但编译后的代码绝对有必要不更改这些向量,因为这会损坏当前R会话中的对应R向量此外,委员会认为,.C64()提供了一种分配零初始化向量的有效方法,这些向量通常用于返回编译函数的结果。为了实现这一点,必须指定意图“write ",并将相应的R向量传递给”. 必须属于类该类的R对象包含类型和长度的信息,然后由.C64()用于分配相应的向量。因此,避免了复制零初始化向量。类“vector_dc” 的向量例如,不传递R vectorvector(mode =R> vector_dc(mode =“numeric”,length = 8)$mode[1] “数字”$长度[1]8attr(,“类别”)[1]“vector_dc”“list”请注意,指定合适的Intent可以通过避免不必要的R向量复制以及避免SIGNATURE =“int64 "类型参数的不必要的double到64位整数和64位整数到double转换来有关性能相关参数的更多详细信息,请参见补充材料的第S2节和软件包手册[20]。2.2. 软件构架函数.C64()使用MIC中的函数.External()将所有提供的参数直接传递给C函数dC64()。在对所提供的参数进行基本检查之后,dC64()如图1所示继续进行。二、请注意,流程图显示了编译函数只有一个参数的情况下的过程否则,dC64()对所有参数重复该方案需要强调的一个方面是SIGNATURE =“int64”参数的R向量的转换。 对于这样的参数,double到int64_t的转换是针对intent“readand write”和“read”完成的;请参见标有(a)的框。在这种情况下,复制是不必要的,因为无论如何实现的强制转换都会分配一个新的 向 量 从 int64_t 到 double 的 反 向 转 换 只 针 对 intent“read andwrite”和“write”;请此外,SIGNATURE的一个与intent为“read and write”的“int 64”不同的如果intent是“read”,则不会复制它,如果intent为“write”,则仅当参数的引用状态不为0时,才会复制该参数。R向量在传递给R函数时会增加其引用状态,因此.C64()不能依赖于该机制。相反,避免复制零初始化向量的一种安全方法是传递类 ''vector_dc ''的R对象由于强制转换在计算时间方面是一个昂贵的操作,我们使用openMP将此任务分配给多个线程(如果可用)[22,23]。请注意,使用的线程数可以通过OpenMPController包中的R函数omp_set_num_threads()控制[24]。也可以通过删除标志来编译没有openMP功能的包dotCall64$(SHLIB_OPENMP_CFLAGS)在src/Makevar文件中的源代码。3. 说明性示例我们展示了R包dotCall64中的.C64(),使用它来接口一个示例C函数。补充材料的第S3节提供了该示例的Fortran版本FFI中.C64()和.C()的直接比较显示了FFI的一些局限性,并且使用.C64()可以直接克服这些局限性。此外,语法上的相似性和差异变得明显。我们考虑下面定义的示例C函数R> writeLines(“void get_c(double *input,int *index,double*output){ output[0]= input[index[0] - 1];}",con =“get_c.c”)get_c()接受参数input(double)、index(integer)和output(double),并将input的元素写入index指定的位置以输出。我们在命令行中使用R CMD SHLIB get_c. c编译函数。生成的动态共享对象(在我们的Linux平台上是get_c. so)必须在编译函数被调用之前加载请注意,在下面的R代码中,共享对象的扩展名被替换为.Platform$dynlib.ext,以使代码与平台无关。R>dyn.load(paste0(“get_c”,.Platform$dynlib.ext))可以使用FFI中的.C()来调用C函数get_c()。请注意,使用了R函数as.double()和as.integer(),这确保了传递的R向量的类型与get_c()的签名匹配。R>.C(“get_c”,input=as.double(1:10),index=as.integer(9),output=double(1))$output[1]9接下来,我们尝试使用相同的调用,将长向量x_long传递给get_c()的参数输入。请注意,以下R代码需要最多32 GB的可用内存才能运行。R>x_long- double(2^31); x_long[9]- 9; x_long[2^31]- -1R>.C(“get_c”,input=as.double(x_long),index=as.整数(9),输出= double(1))$输出错误:.C中不支持长向量(参数1)220F. Gerber等人/SoftwareX 7(2018)217−图二、 使用.C64()调用带有一个参数的编译函数时所涉及的进程的流程图。 在预处理阶段,所提供的R向量通过“.” 根据参数NAOK、SIGNATURE和INTENT进行检查和准备。然后,调用用参数.NAME指定的编译函数最后,如果必要的话,在后处理阶段中反向投射向量。正如预期的那样,.C()抛出错误,因为它不支持长向量。可以通过将.C()替换为.C64()。这允许使用长向量x_long计算C函数get_c()。此外,.C64()需要参数SIGNATURE来编码get_c()参数的签名。该信息用于将所有提供的R向量强制为指定的签名。因此,不再需要保证传递的R向量的类型与编译函数的签名匹配。R>install.packages(“dotCall64”)R> library(“dotCall64”)R>.C64(“get_c”, SIGNATURE =c(“double”,“integer”,“double”),input=x_long,index=9,output=double(1))$output[1]9与使用.C()的调用相反,返回长向量x_long的第九个元素。然而,get_c()的参数索引是int类型(32位整数),因此,不能提取位置超过231 1的元素。为了克服这个问题,我们修改了C函数get_c()的定义,并将参数索引声明中的int类型替换为int64_t类型,该类型在C头文件stdint. h中定义。R>writeLines(“#include stdint.h>void get64_c(double *input,int64_t *index,double *output){ output[0] = input[index[0]- 1];}",con =“get64_c.c”)我们在命令行中使用R CMD SHLIB get64_c. c编译函数,以获得动态共享对象(在我们的平台上为get64_c.so由于int64_t参数,无法使用.C()调用此函数。另一方面,当SIGNATURE参数的第二个元素被设置为“int64”时,.C64()可以接口R>dyn.load(paste0(“get64_c”,.Platform$dynlib.ext))R>.C64(“get64_c”, SIGNATURE =c(“double”,“int64”,“double”),input=x_long,index=2^31,output=double(1))$output[1]-1个在上面的调用中,函数.C64()在调用get64_c()之前将参数索引从double(64位整数的R表示)转换为int64_t类型向量,然后将其从int64_t反向转换为double。默认情况下,对于所有提供的R对象,.C64()的INTENT参数设置为但是,C函数get64_c()只读取F. Gerber等人/SoftwareX 7(2018)217221(and不写)参数输入和索引,只写(但不读)参数输出。为了避免不必要的R对象复制,我们可以修改调用如下。R>.C64(“get64_c”,SIGNATURE =c(“double”,“int64”,“double” ), INTENT=c( “r“, “r“,“w“),input=x_long,index=2^31,output=vector_dc(“numeric”,1))$output[1]-1个注意numeric_dc()的用法,这意味着长度为1的double vec-tor由.C64()构造。如果该参数的SIGNATURE是“int64”,则计算效率更高正如补充材料S2节中的性能测量所示,设置正确的INTENT可以显著减少将大型对象传递给编译代码的时间。4. 结论和影响CRAN接口编译代码上大约有3200个R包,其中大约有1300个(40%)使用R提供的FFI(截至2018-01- 09,另见图1)。①的人。与MIC和R包Rcpp等最近的接口相比,使用FFI有一个主要优势:它不需要用户以R特定的方式调整编译代码这很方便,因为它本质上减少了将编译代码与R函数调用的因此,FFI非常适合在现有的C、C++和Fortran库之上构建高级R环境然而,FFI有严重的局限性,这激发了R包dotCall64中可用的建议接口的开发。dotCall64通过以下创新增强了FFI:(A) 附加的参数SIGNATURE确保了接口的R对象是指定的类型(B) 避免不必要的R对象副本的选项(C) 长向量支(D) 解释R特定的索引长向量(E) 并行执行耗时的铸件创新(A)有助于避免运行时错误,并使dotCall64成为所有FFI当前用户的有趣替代方案。但是,使用dotCall64的主要好处是处理大型对象,这在数据分析中变得越来越重要在这种情况下,创新(B)有助于避免复制被编译代码读取但未被修改的R对象。这导致了相当大的速度和内存增益,如补充材料第S2节中的性能研究所示此外,dotCall64不仅支持长向量(C),还提供了与openMP(E)并行的自动化双到64位整数转换这有助于使用长R向量与编译代码联合;请参阅补充材料的第S4节,了解使用长向量支持扩展R包的策略。dotCall64用于扩展具有长向量支持的R包的一个突出示例是稀疏矩阵代数R包spam,它现在可以处理具有更多231−1个非零元素[25]。确认我们感谢苏黎世大学研究优先计划(URPP)对“全球变化和生物多样性”的支持。附录A.补充数据与本文相关的补充材料可以在https://doi.org/10.1016/j.softx.2018.06.002上找到。引用[1] Eubank RL,Kupresanin A. C++和R中的统计计算。 Chapman&Hall/CRC;2011年。[2] ChambersJM.数据分析软件:用R编程Springer;2008.http://dx.doi.org/10.1007/978-0-387-75936-4。[3] R核心团队写R扩展。奥地利维也纳:R Foundation for Static Computing; 2018R版本3.5.0。网址http://cran.r-project.org/doc/manuals/R-exts.html。[4] 威 克 姆 ·H 先 进 河 Chapman Hall/CRC; 2014. http://dx.doi.org/10 的 网 站 。1201/b17487。[5] [10]杨文,杨文. inline:从R中内联C、C++、Fortran函数调用2015 R软件包版本0.3.14。网址http://CRAN.R-project.org/package=inline。[6] Eddelbuettel D,François R,Allaire J,Ushey K,Kou Q,Russell N,et al.Rcpp:Seamless R and C++ integration,R package version 0.12.14; 2017.网址https://CRAN.R-project.org/package=Rcpp网站。[7] Eddelbuettel D , François R.Rcpp : 无 缝 的 R 和 C++ 集 成 。 J Stat Softw2011;40(8):1http://dx.doi.org/10.18637/jss.v040.i08网站。[8] Eddelbuettel D 与 Rcpp 无 缝 集 成 的 R 和 C++ 。 New York : Springer; 2013URLhttp://www.rcpp.org/book/.[9] Eddelbuettel D,François R,Bates D,Ni B.RcppArmadillo:Armadillo模板线性代数库的Rcpp集成2017URLhttps://CRAN.R-project.org/package=RcppArmadillo。[10] 放大图片作者:Eddelbuettel D,Sanderson C. RcppArmadillo:用高性能C++线 性 代 数 加 速 R 。 Comput Statistist Data Anal 2014;71 : 1054-63.http://dx.doi.org/10.1016/j.csda.2013.02.005网站。[11] Bates D,Eddelbuettel D,François R, Qiu Y,Eigen的作者RcppEigen :Rcpp 集 成 Eigen 模 板 线 性 代 数 库 , R 包 版 本 0.3.3.3.1; 2017 。网 址https://CRAN.R-project。org/package=RcppEigen.[12] 放大图片作者:Bates D.使用RcppEigen软件包的快速和优雅的数值线性代数J Stat Softw 2013;52(5):1http://dx.doi.org/10.18637/jss.v052.i05。[13] Allaire J , François R , Ushey K , Vandenbrouck G , Geelnard M ,Intel.RcppParallel: 用于 Rcpp R包 的并 行编 程工 具版 本 4.3.20; 2016 。 网址https://CRAN.R-project.org/package=RcppParallel。[14] François R,Ushey K,Chambers J. Rcpp 11:R和C++11,R包版本-3.1.2.0;2014.网址https://CRAN.R-project.org/package=Rcpp11。[15] Furrer R , Gerber F , Gerber D , Mösinger K. spam : SPArse Matrix , Rpackage version 2.1-2; 2017.网址https://CRAN.R-project.org/package=spam。[16] Furrer R , Sain SR. spam : A sparse matrix R package with emphasis onMCMC methods for Gaussian Markov random fields.统 计软 件杂 志2010;36(10):1-25. http://dx.doi.org/10.18637/jss.v036.i10网站。[17] Gerber F,Furrer R.面积计数数据的贝叶斯分层模型实施中的陷阱:使用BYM 和 Leroux 模 型 的 说 明 J Stat Softw 2015;63 ( 1 ) : 1-32.http://dx.doi.org/10.18637/jss.v063.c01网站。[18] 萨阿德·Y SPARKIT:A Basic Tool Kit for Sparse Matrix Computations; 1994.网址http://www-users.cs.umn.edu/~saad/software/SPARSKIT/index.html。[19] Oehlschlägel J. bit64:A S3 Class for Vectors of 64 bit Integers,R packageversion 0.9-7; 2017.网址https://CRAN.R-project.org/package=bit64。[20] Mösinger K,Gerber F,Furrer R.dotCall 64:支持长向量的增强外部函数URLhttps://CRAN. R-project.org/package=dotCall64。[21] 威克姆·H testthat:开始测试。 R J 2011;3:5//journal.r-project.org/archive/2011-1/RJournal_2011-1_Wickham.pdf网站。[22] Dagum L,Menon R. OpenMP:用于共享内存编程的行业标准API。IEEEComput Sci Eng 1998;5(1):46-55. http://www.example.comdx.doi.org/10.1109/99.660313。[23] OpenMP 架 构审 查 委员 会 。OpenMP 应 用程 序 接口 , 版 本4.5; 2016 。 网 址http://www.openmp.org。[24] Guest S. OpenMPController : 动 态 控 制 OpenMP 线 程 数 , R 包 版 本 0.2-5;2017。URLhttp://CRAN.R-project.org/package=OpenMPController。[25] Gerber F,Mösinger K,Furrer R.扩展R包以支持64位编译代码:一个带有spam64和GIMMS NDVI_3g数据的说明。Comput Geosci 2017;104:109-19.http://dx.doi.org/10.1016/j.cageo.2016.11.015网站。
下载后可阅读完整内容,剩余1页未读,立即下载
cpongm
- 粉丝: 4
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- CIC Compiler v4.0 LogiCORE IP Product Guide
- G989.pdf
- G988中文版.pdf
- G9807.1中文版.pdf
- 从零开始做产品:产品汪
- URP-DeferredShading方案(高清版)
- Landsat/Sentinel-2 地表反射数据集说明文档(算法)HLS-ATBD-V15-provisional.pdf
- 本地部署开源大模型的完整教程LangChain + Streamlit+ Llama
- 【速记稿】科学引领智能变革——人工智能向善 共筑人类福祉(1).doc
- 技术展望2024 | AI拐点-重塑人类潜力.pdf
- 科学智能(AI4S) 全球发展观察与展望.pdf
- 面向企业的 生成式 AI 和 ML.pdf
- 使用深度学习技术来制作游戏内容.pdf
- 人工智能(AI)X-CUBE-AI扩展包入门指南-.pdf
- 衍生式设计:重新定义 未来制造的无限可能.pdf
- 1_00_尚硅谷大数据项目之docker.docx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功