r - Gpu processing R(如何使用 Gpu 处理在数据集的子集上运行函数)
问题描述
我有一个大型数据集(大约 500 万个观察值)。观察记录了由“类型”表示的不同类型的子事件来自特定事件的总收入。数据的小复制如下:
Event_ID = c(1,1,1,1,1,2,2,2,2,2,3,3,3,3)
Type=c("A","B","C","D","E","A","B","C","D","E","A","B","C","D")
Revenue1=c(24,9,51,7,22,15,86,66,0,57,44,93,34,37)
Revenue2=c(16,93,96,44,67,73,12,65,81,22,39,94,41,30)
z = data.frame(Event_ID,Type,Revenue1,Revenue2)
我想使用 GPU 内核来运行我编写的函数(我从未尝试过 GPU 处理,所以完全不知如何开始)。实际功能需要很长时间才能运行。我在下面展示了一个非常简单的函数版本:
Total_Revenue=function(data){
full_list=list()
event_list=unique(data[,'Event_ID'])
for (event in event_list){
new_data=list()
event_data = data[which(data$Event_ID==event),]
for (i in 1:nrow(event_data)){
event_data[i,'Total_Rev'] = event_data[i,'Revenue1']+event_data[i,'Revenue2']
new_data=rbind(new_data,event_data[i,])
}
full_list=rbind(full_list,new_data)
}
return(full_list)
}
Total = Total_Revenue(data=z)
print(Total)
这个简化的版本功能如下:
a) 将数据集分解为子集,使得每个子集仅包含 1 个唯一事件。
b) 对于每个观察,循环遍历所有观察并计算收入 1+收入 2。
c) 存储子集,最后返回新数据集。
由于我之前没有经验,所以我正在查看一些 R 包。我找到了 gpuR 包并安装了它。但是,我很难理解如何实现这一点。另外问题是我的编码背景非常薄弱。在过去的一年里,我自学了一些东西。
任何帮助/线索将不胜感激。我也愿意使用任何替代包。如果我错过了什么,请告诉我。
PS 我还使用以下命令对我的系统进行了快照:
str(gpuInfo())
我附上输出供您参考:
PPS 请注意,我的实际功能有点复杂和冗长,运行需要很长时间,这就是我想在这里实现 gpu 处理的原因。
解决方案
GPU 编程不是灵丹妙药。它仅适用于某些问题。这就是为什么该gpuR
软件包提供了 GPU 基向量和矩阵,允许使用 GPU 完成线性代数运算。如果您的问题不是线性代数问题,这将无济于事。但是,请注意,许多问题都可以这样表述。
我们无法判断您的问题是否属于此类,因为您(可能)过度简化了您的代码:
> print(Total)
Event_ID Type Revenue1 Revenue2 Total_Rev
1 1 A 24 16 40
2 1 B 9 93 102
3 1 C 51 96 147
4 1 D 7 44 51
5 1 E 22 67 89
6 2 A 15 73 88
7 2 B 86 12 98
8 2 C 66 65 131
9 2 D 0 81 81
10 2 E 57 22 79
11 3 A 44 39 83
12 3 B 93 94 187
13 3 C 34 41 75
14 3 D 37 30 67
由于Total_Rev
只是 和 的总和Revenue1
,因此Revenue2
您可以更轻松地完成此操作:
> z$Total_Rev <- z$Revenue1 + z$Revenue2
> z
Event_ID Type Revenue1 Revenue2 Total_Rev
1 1 A 24 16 40
2 1 B 9 93 102
3 1 C 51 96 147
4 1 D 7 44 51
5 1 E 22 67 89
6 2 A 15 73 88
7 2 B 86 12 98
8 2 C 66 65 131
9 2 D 0 81 81
10 2 E 57 22 79
11 3 A 44 39 83
12 3 B 93 94 187
13 3 C 34 41 75
14 3 D 37 30 67
这是一种简单的矢量化形式,可以帮助您摆脱(某些)for
循环。而且由于您的外for
循环看起来不同Event_ID
,因此研究分组和聚合技术也可能有意义。这些可以通过基础 R、data.table
包、tidyverse
/dplyr
和可能的其他工具来完成。我正在使用后一种方法,因为我喜欢它的语法对新手最友好。但是,data.table
如果您有大型数据集,它可能是适合您的工具。所以这里有一个非常简单的聚合来计算每个的平均值Event_ID
:
Event_ID = c(1,1,1,1,1,2,2,2,2,2,3,3,3,3)
Type=c("A","B","C","D","E","A","B","C","D","E","A","B","C","D")
Revenue1=c(24,9,51,7,22,15,86,66,0,57,44,93,34,37)
Revenue2=c(16,93,96,44,67,73,12,65,81,22,39,94,41,30)
z = data.frame(Event_ID,Type,Revenue1,Revenue2)
library(dplyr)
z %>%
mutate(Total_Rev = Revenue1 + Revenue2) %>%
group_by(Event_ID) %>%
summarise(average = mean(Total_Rev))
#> # A tibble: 3 x 2
#> Event_ID average
#> <dbl> <dbl>
#> 1 1 85.8
#> 2 2 95.4
#> 3 3 103
推荐阅读
- architecture - 当控制器输入错误时会发生什么?它是否应该将错误的输入传播到 UseCaseInteractor?
- java - 如何从回收视图中获取按钮单击时的文本视图?
- github - 对于使用 VS Code 的远程开发,当我执行 GIT 克隆时,存储库如何到达远程计算机?
- ruby-on-rails - RSpec 控制器测试 - ActionController::UnfilteredParameters:无法将未经许可的参数转换为哈希
- sql - 如何编写条件以执行 for 循环不返回任何行的操作
- reactjs - redux-persist 中没有更新新的 store 结构
- javascript - Array.push 不是函数,在从 localstorage 检索的数组上
- css - 如何在不按 CTRL + F5 的情况下使 Elementor 更改可见?
- python - 当另一个线程上的函数完成python时停止一个线程
- java - 使用 ArgumentsMatchers 和 Mockito 模拟类类型参数 - Mongo 聚合 Spring Webflux