CoderCastrov logo
CoderCastrov
Параллельная обработка

Параллельные подключения к API в R

Параллельные подключения к API в R
просмотров
4 мин чтение
#Параллельная обработка

Способ сэкономить много времени.

Создание нового набора данных является одной из задач, с которыми сталкиваются сегодня данные ученые и аналитики. Один из популярных способов создания набора данных - это сбор информации с различных веб-сайтов в соответствии с вашими потребностями. Но, как вы знаете, это занимает много времени, поэтому ускорение этого процесса без использования нескольких виртуальных машин или кластеров - это хорошо иметь в своем инструментарии для работы с данными. Здесь мы рассмотрим подробности о том, как выполнять параллельные подключения к API с использованием R.


Это простое руководство о том, как использовать параллельные вычисления. Идея заключается в том, что каждый поток/рабочий/ядерный процессор вашего компьютера использует отдельное подключение для доступа к веб-сайту, поэтому вам не нужно ждать ответа от API или загрузки динамического веб-сайта, чтобы начать парсить другой. Просто добавьте несколько простых команд в свой код и упакуйте его в умном режиме, и вы сможете значительно сэкономить время в процессе.


Параллельное подключение к API

Мы собираемся начать с использования R и параллельного подключения к API. Это позволит нам более эффективно загружать информацию, подобно открытию нескольких вкладок в веб-браузере. В качестве примера мы будем использовать OMDB API. Это API предоставляет доступ к большому количеству информации о фильмах. В нашем тесте мы использовали API для загрузки постеров фильмов и сохранения их локально для последующей обработки.

1.- Загрузка библиотек

Первый шаг - загрузить все необходимые библиотеки. Для настройки параллельного подключения в нашем коде мы будем использовать библиотеку future. Эта библиотека устанавливает метод параллельной обработки, который мы собираемся использовать. Для параллельных функций мы выбираем пакет furr. Этот пакет является будущей версией пакета purrr.

library(RCurl)
library(curl)
library(future)
library(furrr)

2.- Создание функции

Во-вторых, нам нужно создать новую функцию. Эта функция будет использоваться для подключения к API и загрузки данных. Здесь мы можем изменить код подключения к API на код для парсинга веб-страниц.

Для нашей цели, чтобы показать, как это сделать, функция просто будет открывать соединение с помощью curl с API Poster и загружать изображение в новый каталог под названием images.

imgAPI <- '[http://img.omdbapi.com/?apikey=_[your-own-api-key]_'](http://img.omdbapi.com/?apikey=9c9e16a&i=tt%27)
rootDir <- 'images/'
get_img <- function(id){
  url <- paste0(imgAPI,str_pad(id, 7, pad = "0"))
  if(url.exists(url)){
    curl_download(url = url ,destfile = paste0(rootDir,'tt',id,'.png'))
  }
}

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

3. Запустите future_map на всех ваших соединениях

Наконец, нам нужно запустить нашу ранее созданную функцию на нашем списке ссылок. Для этого мы используем future_map, параллельную версию функции map. Именно здесь происходит параллельное соединение.

#загрузите файл со списком идентификаторов фильмов для создания API-ссылок
links <- read_csv('links.csv')
future_map(links, get_img)

ВАЖНО: Чтобы наш код знал, что ему нужно выполняться параллельно, нам нужно указать ему, как это сделать и сколько различных ядер использовать. Есть 2 функции из библиотеки future, которые позволяют нам это сделать: availableCores() и plan(). Первая функция считывает информацию о том, сколько ядер есть на нашем компьютере, а вторая функция сообщает коду, сколько ядер использовать и как параллелизовать функции future.

n_cores <- availableCores() - 1
plan(multiprocess, workers = cores)

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

4.- Тест и результаты

Используя ранее определенный код, мы проведем небольшой тест, чтобы увидеть, как эти параллельные соединения улучшают скорость загрузки. Для этого теста мы используем 4 различные конфигурации:

  • Без параллельных соединений, используя обычную функцию map.
  • Мультипроцессорный план с настройкой на 3 ядра.
  • Мультипроцессорный план с настройкой на 5 ядер.
  • Мультипроцессорный план с настройкой на 7 ядер.

Количество ядер было выбрано на основе машины с 8 ядрами, оставляя как минимум 1 свободное ядро.

Для теста мы запускаем каждую конфигурацию в 3 разных сценариях, чтобы проверить, как объем влияет на производительность. Эти сценарии основаны на количестве постеров фильмов, которые мы собираемся загрузить (500, 1000, 2500). В каждом сценарии мы запускаем его 5 раз и берем среднее время, которое потребовалось для загрузки всех фильмов.

Результаты показаны на графике ниже.

Выводы

Этот тест показывает, что использование параллельных вычислений для доступа к информации из сети может быть отличным дополнением к нашему инструментарию. Как специалисты по обработке данных, у нас часто возникают проекты, связанные с доступом к API для получения информации, и это способ ускорить этот процесс. Даже если процесс не очень объемный, улучшение значительное.


Вы можете получить доступ к коду эксперимента по этой ссылке на GitHub.