R语言 | 多线程包 RcppParallel 测试

2 篇文章 0 订阅
2 篇文章 0 订阅

1. Overview 概述

(1) CRAN

  • https://cran.microsoft.com/snapshot/2022-05-30/web/packages/RcppParallel/index.html

Rcpp进行并行编程的高阶函数。比如, parallelFor() 函数可以用于把标准顺序执行的 for 循环转换为并行的;parallelReduce() 可用于累加求和等。
High level functions for parallel programming with ‘Rcpp’. For example, the ‘parallelFor()’ function can be used to convert the work of a standard serial “for” loop into a parallel one and the ‘parallelReduce()’ function can be used for accumulating aggregate or other values.

(2) 源码

  • https://rcppcore.github.io/RcppParallel/

RcppParallel 提供了完整的创建可移植、高性能并行算法的工具,无需直接操作系统线程。

RcppParallel provides a complete toolkit for creating portable, high-performance parallel algorithms without requiring direct manipulation of operating system threads. RcppParallel includes:

RcppParallel 包括:

  • Intel TBB, 一个C++库,用于广泛的并行算法和数据结构(仅限于win, OS X, Linux 和 Solaris x86)
    Intel TBB, a C++ library for task parallelism with a wide variety of parallel algorithms and data structures (Windows, OS X, Linux, and Solaris x86 only).

  • TinyThread,一个可移植的使用操作系统线程的C++库。
    TinyThread, a C++ library for portable use of operating system threads.

  • RVector and RMatrix 包装类,安全、方便的在多进程中访问R数据结构。
    RVector and RMatrix wrapper classes for safe and convenient access to R data structures in a multi-threaded environment.

  • 高性能函数(parallelFor and parallelReduce),使用 Intel TBB 作为后台,如果操作系统支持,其他平台使用 TinyThread
    High level parallel functions (parallelFor and parallelReduce) that use Intel TBB as a back-end on systems that support it and TinyThread on other platforms.

2. 实例

实现一个对矩阵每个元素加上0-100的任务。

主机是12线程 Ubuntu 20.04系统。

R 4.1.1
Rcpp v1.0.9
RcppParallel v5.1.5

(1) R code

# https://rcppcore.github.io/RcppParallel/

library(Rcpp)
# form1: as string
Rcpp::cppFunction("
  int add2(int x, int y){
     return x+y;
  }  ")

add2(2,10)


# form2: from file
library("RcppParallel")
Rcpp::sourceCpp("./backup/demo.RCpp.cpp")

mat1=matrix(0:11, nrow=2);mat1
rs=parallelMatrixSqrt(mat1); rs

output:

> rs=parallelMatrixSqrt(mat1); rs
tid=3990719
tid=3990858
tid=3990859
tid=3990863
tid=3990865
tid=3990866
tid=3990864
tid=tid=3990857
tid=3990867
3990861
tid=3990862
tid=3990860
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,] 5050 5052 5054 5056 5058 5060
[2,] 5051 5053 5055 5057 5059 5061

(2) C++ code

Worker class 的 operator 是干啥的?
是具体执行for循环的代码。

  • 我们定义了自定义函数add10,对每个具体元素进行转换。
  • 为了模拟的更像,我们让函数先休息1s,然后再执行。
  • 为了证明是多线程还是多进程,输出其pid和cid号,证明是多线程,而不是多进程。

$ cat backup/demo.RCpp.cpp

// [[Rcpp::depends(RcppParallel)]]
#include <Rcpp.h>
#include <RcppParallel.h>

namespace Ad10{
#include <unistd.h>
#include<iostream>

#include <sys/unistd.h>
#define gettid() syscall(__NR_gettid)

using namespace std;
int add10(int x){ //自定义函数,输入一个值,处理后返回结果;并行的每个具体子任务
  usleep(1000000);
  for(int i=0; i<=100; i++){
    //std::cout << x << std::endl;
        x +=  i;
  }
  //cout << "pid=" << getpid() << endl;
  cout << "tid=" << gettid() << endl; //一个进程,输出进程号
  return x;
}
}

using namespace Rcpp;
using namespace RcppParallel;



struct SquareRoot : public Worker
{
  // source matrix
  const RMatrix<double> input;

  // destination matrix
  RMatrix<double> output;

  // initialize with source and destination
  SquareRoot(const NumericMatrix input, NumericMatrix output)
  : input(input), output(output) {}

  // take the square root of the range of elements requested
  void operator()(std::size_t begin, std::size_t end) { //把顺序执行的for变成 多线程 并行执行
    std::transform(input.begin() + begin,
                   input.begin() + end,
                   output.begin() + begin,
                   Ad10::add10); //调用自定义函数
                  //::sqrt); //调用c++的平方运算
                  //::fabs); //调用c++的求绝对值
  }
};




// [[Rcpp::export]]
NumericMatrix parallelMatrixSqrt(NumericMatrix x) {

  // allocate the output matrix
  NumericMatrix output(x.nrow(), x.ncol());

  // SquareRoot functor (pass input and output matrixes)
  SquareRoot squareRoot(x, output);

  // call parallelFor to do the work
  parallelFor(0, x.length(), squareRoot); //调用并行形式的for循环,变换矩阵的每个元素

  // return the output matrix
  return output;
}

(3) 效果

当把C++代码中的 add10 中for循环修改为 i<=2e9 ,再执行,能看到CPU短暂跑满,也就是确实启动了多线程。

在这里插入图片描述

3. 更多用法看文档

  • Rcpp Quick Reference Guide https://dirk.eddelbuettel.com/code/rcpp/Rcpp-quickref.pdf
  • https://rcppcore.github.io/RcppParallel/
  • 作者在Rstudio上的推广视频: RcppParallel provides a complete toolkit for creating safe, portable, high-performance parallel algorithms
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值