Экспорт параллельного вызова Foreach в среду - PullRequest
0 голосов
/ 02 марта 2019

Я хотел бы экспортировать аутс-путы из foreach в среду.Я извлекаю данные временных рядов из финансов Yahoo.

library(quantmod)
library(foreach)
library(parallel)
library(doParallel)
registerDoParallel(cores=2)

hub = new.env()
tickers = c("NKE", "AAPL", "MSFT", "TSLA", "MPC", "PEP", "GIS", "MA","V", "CAT", "KHC", "AMZN", "NFLX", "GS", "MS", "BAC", "GE", "KO", "JPM", "AMAT", "ABT", "BIIB")

#I have tried 2 methods below.
#The first gives me a list of just the ticker names.
#The second puts the data into a list. I am looking for an enviornment
foreach(r = tickers, .packages = "quantmod") %dopar% lapply(r, getSymbols, env = hub)

enviro = foreach(r = tickers, .packages = "quantmod")%dopar% lapply(r, getSymbols, auto.assign = F)

class(enviro)
[1] "list"

Среда должна выглядеть следующим образом (она работает, когда я не запускаю ее в цикле foreach).

hub = new.env()
#the following line of code takes about 1 min. Just a heads up
getSymbols(tickers, env = hub)

1 Ответ

0 голосов
/ 02 марта 2019

Вопрос очень неясен, но из вашего вопроса кажется, что вы пытаетесь объединить выходы в одну среду, чтобы получить большую скорость.

Теперь вы, вероятно, должны отметить несколько вещей.quantmod::getSymbols имеет некоторые накладные расходы на каждый звонок.При использовании текущего метода вы должны увидеть снижение производительности из-за функции, вызываемой для каждого символа.

Оптимизации

Один из способов уменьшить накладные расходы - разделить каждый расчет на куски.Пакет foreach основан на пакете iterators, который позволяет довольно просто разбить вычисления на куски.

nworker = 2
registerDoParallel(cores = nworker)
tickers = matrix(c("NKE", "AAPL", "MSFT", "TSLA", "MPC", "PEP", "GIS", "MA","V", "CAT", "KHC", "AMZN", "NFLX", "GS", "MS", "BAC", "GE", "KO", "JPM", "AMAT", "ABT", "BIIB"), ncol = 1)
tickerIter <- iterators::iter(tickers, by = 'row', #I made a 1 column matrix, so i will iterate over each row.
                              chunksize = ceiling(length(tickers)/nworker) #Set chunk size, such that each worker gets 1 job.
)

В приведенном выше коде tickerIter теперь является итератором для всехсимволы с длиной фрагмента nworker.Таким образом, каждый работник (ядро) получает только один кусок, и нам придется экспортировать и импортировать из каждого работника только один раз.tickerIter будет указан в качестве аргумента в цикле foreach вместо необработанных тикеров.Чтобы увидеть, как итератор выводит в цикл foreach, вы можете попробовать выполнить nextElem(tickerIter), который выведет один блок. Обратите внимание , однако, что вам нужно будет переназначить итератор, так как порция не будет назначена в цикле foreach, если она уже была выведена с использованием nextElem.

Объединение в среду

Из вопроса вы хотите объединить вывод в единую среду.Делать это непосредственно в foreach просто невозможно, по крайней мере, без опасности сбоя сеанса R.Foreach по умолчанию выполняет параллелизацию путем создания нескольких R-сеансов, экспорта данных и выполнения предоставленного кода / выражения.Таким образом, вам придется подключиться к текущему R-сеансу и назначить переменные окружению через этот хук.Это не рекомендуется.

Но foreach содержит аргумент .combine, которому можно назначить настраиваемую функцию для объединения.Кроме того, если функция предназначена для объединения любого количества входов, при использовании .multicombine = TRUE функция будет выполняться только один раз для каждого выхода.

Я не понимаю, почему вы хотели бы специально добавить их в среду концентратора, поэтому в приведенном ниже примере кода выходные данные вместо этого объединяются в один список.Затем список можно преобразовать с помощью list2env для экспорта вывода в определенную среду.

Примечание использование tickerIter вместо необработанных тикеров.

output <- foreach(r = tickerIter, 
                  .combine = function(...){
                    c(...) #Combine all outputs into a list
                  }, 
                  .multicombine = TRUE, 
                  .packages = "quantmod")%dopar% {
                    currenv <- environment() 
                    getSymbols(r, currenv)
                    as.list(currenv)
                  }
#If you really want it in a specific environment, you could use: (Could also be used in .combine)
list2env(output, hub)
...