Обработка Gpu R (Как использовать обработку Gpu для запуска функции на подмножествах набора данных) - PullRequest
0 голосов
/ 20 января 2019

У меня большой набор данных (около 5 миллионов наблюдений).Наблюдения регистрируют общий доход от конкретного события по разным типам вложений, обозначаемых как «тип».Ниже приведена небольшая репликация данных:

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) Разбейте набор данных на подмножества так, чтобы каждое подмножествопринимает только одно уникальное событие.

b) Для каждого наблюдения выполните цикл по всем наблюдениям и рассчитайте Доход1 + Доход2.

в) Сохраните подмножества и в конце верните новый набор данных.

Поскольку у меня нет предыдущего опыта, я смотрел на некоторые пакеты R.Я нашел пакет gpuR и установил его. Однако мне сложно понять, как это реализовать.Также проблема в том, что мой фон кодирования очень слабый.Я сам научил себя некоторым вещам за последний год.

Любая помощь / ведет будет высоко оценен.Я открыт для использования любых альтернативных пакетов.Пожалуйста, дайте мне знать, если я что-то пропустил.

PS Я также сделал снимок своей системы, используя следующую команду:

str(gpuInfo())

Я прилагаю вывод для вашей справки:

enter image description here

PPS Обратите внимание, что моя фактическая функция немного сложна и длинна, и ее запуск занимает много времени, поэтому я хочу реализовать обработку gpu здесь.

1 Ответ

0 голосов
/ 21 января 2019

Программирование на GPU - не серебряная пуля. Это хорошо работает только для определенных проблем. Вот почему пакет gpuR предоставляет базовые векторы и матрицы графического процессора, позволяющие выполнять операции линейной алгебры с использованием графического процессора. Это не поможет вам, если ваша задача не является проблемой линейной алгебры. Тем не менее, обратите внимание, что многие проблемы можно сформулировать , например, таким образом.

Мы не можем определить, относится ли ваша проблема к этой категории, поскольку вы (возможно) слишком упростили свой код:

> 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
...