[R 데이터 분석] Using C/C++ in R , R언어에서 C/C++ 사용하기

Resources

C and C++ Basics

These are compiled languages and hence a compiler is needed to transform a human interpret able program into a machine executable one. The most commonly use compiler is gcc. This is already installed on most Linux distributions, including all the servers we have commonly used in this course. If you wish to compile C/C++ programs on your personal computer, you will need to install a compiler.
Mac users should download Xcode from Apple’s app store. Windows users should investigate Rtools or Cygwin.

There are three important differences from R

  • Variables and functions need to be declared before use.
  • Arrays are indexed from zero.
  • Arrays are stored in row-major order.
  • Statements are delimited using semicolons “;”.
  • Loops have minimal overhead and hence generally do not need to be avoided.

C Basics

We will review the following topics from C Tutorial:

  • Program Structure
  • Basic Syntax
  • Data types (Integer and Floating Point Types)
  • Variables
  • Operators (Arithmetic, Relational, Logical and Assignment)
  • Loops
  • Arrays
  • Pointers
  • Type Casting

We will not review these as they work very much like in R:

  • Decision Making

The remaining sections are mostly beyond the scope of what we will discuss here.

Calling C functions from R

We can call a function written in C from R using .C() or .call(). We begin with .C as it is simpler.

Using .C()

The basic recipe for using .C is as follows:

  • Write a function in .C that returns void and stores the desired result in one or more arguments expressly created for this purpose. Your function should have a C_ prefix.

  • Compile your function into a shared library accessible to R using this command: R CMD SHLIB my_func.c with my_func.c replaced by your c program.

  • Within an active R session, link to the shared library using dyn.load("my_func.so").

  • Write an R wrapper to call your C function using .C with the following syntax: .C("C_my_func", arg1, arg2). The reason to use an R wrapper is to ensure that the arguments passed are of the correct size and type in order to avoid potentially fatal errors.

The middle two steps can be avoided by including these functions into an R package. We will discuss this briefly when turning to C++ and Rcpp.

A conceptual key to understanding how .C works is realizing that function arguments are passed as pointers to objects in memory rather than by value.

We will look at some examples of C coding available here.

Using .Call()

We can use .Call() to create and modify R level objects directly using functions in C. R level objects are of type SEXP for “S-expression”. These types are defined in the header file Rinternals.h which should be included in all C functions to be called with .Call().

When we create R level objects, we must protect them from garbage collection using PROTECT or a similar function. We later UNPROTECT them to allow the memory to be reallocated.

Recall that scalars in R are length one vectors. Consequently, the must be coerced to C type scalars to be uses as such. This can be done using the C functions as*: asLogical, asInteger, asReal, CHAR(asChar()).

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

Here is a simple example using the inline::cfunction.

library(inline)
## 
## Attaching package: 'inline'
## The following object is masked from 'package:Rcpp':
## 
##     registerPlugin
seqn = cfunction(signature(n_="integer", start_="integer"), 
 body="
 int i, n = asInteger(n_), start=asInteger(start_);
 SEXP out = PROTECT(allocVector(INTSXP, n));
 for(i=0; i<n; ++i){
   INTEGER(out)[i]=i+start;
 }
 UNPROTECT(1);
 return out;
")
seqn(8, 3)
## [1]  3  4  5  6  7  8  9 10
fib = cfunction(c(n_="integer"), body=
  "
  /* Declaratations */
  int n = asInteger(n_);
  SEXP out = PROTECT(allocVector(INTSXP, n));

  /* Function Body */
  INTEGER(out)[0] = 1;
  if(n > 1)  INTEGER(out)[1]=1;
  if(n > 2)
    {
      for(int i=2; i<n; i++)
        {
        INTEGER(out)[i] = INTEGER(out)[i-2] + INTEGER(out)[i-1];
        }
    }

  /* Clean up and return */
  UNPROTECT(1);
  return out;
  ")
fib(10)
##  [1]  1  1  2  3  5  8 13 21 34 55

Modifying inputs

Be careful about modifying input arguments without duplicating first as other R objects may point to the same location in memory owing to “copy-on-modify” semantics.
Here is a quick example from p. 441 of Advanced R using the “inline” package.

add_three = cfunction(c(x="numeric"),
  "
   REAL(x)[0] = REAL(x)[0] + 3;
   return x; 
  ")
y <- x <- 1
add_three(x)
## [1] 4
x
## [1] 4
y
## [1] 4

Here is a corrected version in which the argument is duplicated rather than modified in place.

add_3 = cfunction(c(x_="numeric"),
  "
   SEXP x = PROTECT(duplicate(x_));
   REAL(x)[0] = REAL(x)[0] + 3;
   UNPROTECT(1);
   return x; 
  ")
y <- x <- 1
add_3(x)
## [1] 4
x
## [1] 1
y
## [1] 1

Interfacing with C++ via Rcpp

The Rcpp package greatly simplifies the process of exposing functions written in C++ to R.

Using sourceCpp

We can use the function sourceCpp to read a function written in C++ into R interactively. The function takes care of the compilation using R CMD SHLIB and automatically generates an R wrapper for the underlying function. The shared library and other files will be written to the directory specified by cacheDir which defaults to a temporary directory for automated clean up.

To use a C++ function via sourceCpp:

  1. Write a your C++ function in a file with extension .cpp.
  2. In the source file, be sure to #include <Rcpp.h>.
  3. Designate functions exposed to R using the tag // [[Rcpp::export]].
  4. Compile and source your function using sourceCpp() and a link to the file.

Here are some minimal examples based on generating Fibonacci numbers. You can download the source code here.

The final Fibonacci example here makes two changes from the previous example:

  1. We add the line using namespace rcpp; to avoid having to type the prefix Rcpp:: when referring to the Rcpp namespace. This is much like using library() within R to add a package to the search path.

  2. We show how to print to the R console from within the C++ function using Rcout. This can be useful for manual debugging.

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
IntegerVector FibCpp2(int n)
{
  // Error checking
  if(n <= 0)
    {
      throw std::range_error("n must be a positive integer");
    }

  // Allocate memory
  IntegerVector out(n);
  out[0]=1;

  Rcout << "Starting computations ... ";
  // Compute additional terms
  if(n > 0)
    {
      out[1]=1;
      int i;
      for(i=2; i<n; i++)
        {
          out[i] = out[i-1] + out[i-2];
        }
    }

  Rcout << "done." << std::endl;
  return out;
}
sourceCpp('~/Stats506/FibCPP2.cpp')
FibCpp2(10)
## Starting computations ... done.
##  [1]  1  1  2  3  5  8 13 21 34 55

Example

Here is another simple example.

Building a package with Rcpp

The sourceCpp function is convenient for interactive use and initial development. However, for larger projects with multiple functions it is better to maintain the code base using an R package. Rcpp automates much of the work involved in doing this via the compileAttributes function.

This function creates a C++ wrapper to any C++ functions tagged with the // [[Rcpp::export]] attribute that handles type conversion and an R wrapper that calls this function in turn. This makes for a relatively seamless process in which you only occasionally need to look into the translation details.

In the download above is avery simple R package Pkg with the getRegion function from the previous example.

[출처] https://jbhender.github.io/Stats506/F17/Using_C_Cpp.html

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
공지 오라클 기본 샘플 데이터베이스 졸리운_곰 2014.01.02 94709
공지 [SQL컨셉] 서적 "SQL컨셉"의 샘플 데이타 베이스 SAMPLE DATABASE of ORACLE 가을의 곰을... 2013.02.10 85792
공지 [G_SQL] Sample Database 가을의 곰을... 2012.05.20 102611
138 [tensorflow] TensorFlow 2.x 에서 1.x 코드 사용하기 졸리운_곰 2022.08.07 1366
137 [tensorflow] 텐서플로 - TF 1.*버전 vs 2.*버전 file 졸리운_곰 2022.08.07 1307
136 [python][tensorflow - gpu] [파이썬] 텐서플로(TensorFlow) 설치하는 방법, 딥러닝 환경 구축하기 file 졸리운_곰 2021.08.17 1249
135 [tensorflow 설치] windows에서 tensorflow-gpu 1.x 버전 설치, python - 이전 버전의 Tensorflow GPU 설치 졸리운_곰 2021.08.17 1057
134 [한글 처리][tensorflow] 한글 자연어처리를 위한 도구들, 자료들, 정보들을 정리해 보았습니다. 졸리운_곰 2021.08.11 1510
133 [딥러닝] [텐서플로우][SSAC X AIFFEL] 작사가 인공지능 만들기 file 졸리운_곰 2021.07.10 1103
132 [모바일 머신러닝 라이브러리 및 자료] Awesome-Mobile-Machine-Learning 졸리운_곰 2021.01.14 2059
131 머신 딥러닝 관련 개발 프로세스 file 졸리운_곰 2021.01.06 2122
130 텐서플로우 소스 구조 분석 (TensorFlow Internal) file 졸리운_곰 2021.01.05 1443
129 [러닝 텐서플로]Chap07.2 - 텐서플로 추상화와 간소화, TFLearn 졸리운_곰 2021.01.03 858
128 [러닝 텐서플로]Chap07.1 - 텐서플로 추상화와 간소화, Estimator file 졸리운_곰 2021.01.02 1067
127 [러닝 텐서플로]Chap06 - 텍스트2: word2vec, Bidirectional RNN, GRU, 임베딩 시각화 file 졸리운_곰 2020.12.28 1323
126 [러닝 텐서플로]Chap05 - 텍스트 1: 텍스트와 시퀀스 처리 및 텐서보드 시각화 file 졸리운_곰 2020.12.28 1083
125 [러닝 텐서플로]Chap04 - 합성곱 신경망 CNN file 졸리운_곰 2020.12.28 1225
124 Making TensorFlow Models Portable Using ONNX file 졸리운_곰 2020.12.24 4475
123 [러닝 텐서플로]Chap03 - 텐서플로의 기본 이해하기 file 졸리운_곰 2020.12.24 1520
122 [러닝 텐서플로]Chap02 - 텐서플로 설치 및 실행 file 졸리운_곰 2020.12.24 880
121 [러닝 텐서플로]Chap01 - 텐서플로 란? file 졸리운_곰 2020.12.24 1334
120 러닝 텐서플로 - 0 file 졸리운_곰 2020.12.24 2068
119 [tensorflow] 텐서플로로 음악 작곡 : Generate Music in TensorFlow 졸리운_곰 2020.09.27 1350
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED