2

У меня есть много изображений, которые мне нужно запустить через java-программу для создания большего количества файлов изображений - неловко параллельного корпуса. Каждый входной файл составляет около 500 мб, для обработки требуется около 4 ГБ памяти и занимает от 30 секунд до 2 минут для запуска. Java-программа многопоточна, но больше выгоды происходит от параллелизации входных файлов, чем от использования большего количества потоков. Мне нужно запускать процессы несколько раз в день (я не хочу включать/выключать кластер вручную и не платить за него 24/7).Параллельная обработка файлов с использованием облачных сервисов

Я немного потерял в разнообразии вариантов облака там:

  • Amazon lambda имеет недостаточно системных ресурсов (не хватает памяти).
  • Google Cloud DataFlow, похоже, что мне нужно будет написать собственный источник конвейера, чтобы использовать их ведра для облачного хранения. Хорошо, но я не хочу тратить время на это, если это не подходящее решение (что может быть, я пока не могу сказать).
  • Amazon data pipeline выглядит как эквивалент Google Cloud DataFlow. ()
  • Google Cloud Dataproc, это не карта/сокращение ситуации hadoop-y, но может работать, тем не менее. Я бы предпочел не управлять своим собственным кластером.
  • Google вычислит двигатель или AWS с автомасштабированием, и я просто запускаю процессы для каждого ядра на машине. Больше управления от меня, но нет API, чтобы учиться.
  • Microsoft Data Lake еще не выпущен и выглядит hasoop-y.
  • Microsoft Batch кажется вполне уместным (но я спрашиваю, потому что мне интересно узнать другие варианты).

Может кто-нибудь посоветует, какие подходящие решения будут для этого?

+0

Есть ли какая-то особая причина, по которой вы хотите избежать Hadoop (или Spark) для этой обработки? Я предполагаю, что вам не нужно переписывать свое приложение, но я хотел попросить вас убедиться. :) – James

+0

@James Я не знаком с Spark/Hadoop, поэтому моя причина может быть ошибочной. Java-программа - большая сторонняя, которая практически не может быть переписана. (Хотя это может быть завернуто в другой класс java через API.) Практический метод, который я видел, заключался в том, чтобы вызывать системные процессы, которые затем, казалось, делали Spark/Hadoop плохим. ...может быть? – ZachB

+1

Получил это. Да, вы могли бы обернуть его в другой класс Java и запустить его. Это было бы быстро и распределено, но, возможно, не изящно. Для Cloud Dataproc, как только вы создадите кластер, он управляется для вас, поэтому общий уровень управления будет низким. Вы также можете настроить размер кластера динамически в зависимости от необходимости, что может быть приятным. Если вам интересно, LMK (но я не хочу задавать этот вопрос. :) – James

ответ

4

Вы должны иметь возможность сделать это с помощью Dataflow довольно легко. Трубопровод может выглядеть примерно так (при условии, ваши файлы расположены на Google Cloud Storage, ГКС):

class ImageProcessor { 
    public static void process(GcsPath path) { 
     // Open the image, do the processing you want, write 
     // the output to where you want. 
     // You can use GcsUtil.open() and GcsUtil.create() for 
     // reading and writing paths on GCS. 
    } 
} 

// This will work fine until a few tens of thousands of files. 
// If you have more, let me know. 
List<GcsPath> filesToProcess = GcsUtil.expand(GcsPath.fromUri("...")); 
p.apply(Create.of(filesToProcess)) 
.apply(MapElements.via(ImageProcessor::process) 
        .withOutputType(new TypeDescriptor<Void>() {})); 
p.run(); 

Это одна из общей семьи случаев, когда Dataflow используется в качестве embarassingly-параллельной структуры оркестровки, а не обработки данных но он должен работать.

Вам понадобится Dataflow SDK 1.2.0 для использования преобразования MapElements (поддержка Java 8 lambdas - новая версия 1.2.0).

+1

Мне кажется, мне нужно указать Coder. Есть ли тот, который будет работать для 'GcsPath', или мне нужно реализовать свои собственные? Или мне нужно преобразовать в 'String' и сделать новый' GcsPath 'в процессоре? – ZachB

+1

Преобразование в String, вероятно, проще всего. Или вы можете использовать SerializableCoder.of(). – jkff

+1

Спасибо. Полный минимальный пример [здесь] (https://gist.github.com/zbjornson/ac6a378129f1675ca5ff?ts=4). – ZachB

Смежные вопросы