Подтвердить что ты не робот

Как я могу вернуть результат операции mapreduce в запрос API AWS

У меня есть программа, которая выполняет несколько тысяч монте-карло-симуляций, чтобы предсказать результат; Я не могу сказать, что они на самом деле предсказать, так что я буду использовать другой пример из "бесспорного существования Санта-Клаус", так как содержание этих алгоритмов не имеет отношения к данному вопросу. Я хочу знать, как часто посещают каждый квадрат на монополистической доске (чтобы предсказать, какие лучшие свойства купить). Для этого я имитирую тысячи игр и сопоставляю результаты. Моя текущая реализация представляет собой автономное приложение С#, но я хочу перенести его в облако, чтобы я мог предоставить это как услугу - каждый пользователь может получить персонализированные результаты, отправив количество сторон, которые есть у каждой из их костей.

Текущая реализация также довольно медленная - она ​​очень парализуема, поскольку каждая симуляция полностью независима, но у меня есть только 8 ядер, поэтому для завершения полного предсказания требуется около 20 минут, причем около 50000 отдельных симуляторов на моей локальной машине.

План состоит в том, чтобы каждый из них выполнял одно (или несколько) симуляции AWMS-лямбда-функций, а затем сортировал их - в основном, переводил их. Я посмотрел на использование AWS EMR (Elastic MapReduce), но это слишком масштабно для того, что я хочу, и разворачивание экземпляров для запуска только вычислений, по-видимому, занимает больше времени, чем все вычисления в одиночку (что не имело бы значения для мульти- часовой автономный анализ, но я хочу, чтобы низкая латентность отвечала на веб-запрос).

Идеальный, как я вижу, будет:

Lambda 0 - Сгоняет многие другие лямбда-функции, каждый из которых выполняет небольшую часть вычисления. Лямбда 1..N - Параллельно много симуляций (число не является константой). Lambda N + 1 - Составьте все результаты и верните ответ.

Здесь есть каркас lambda mapreduce:

https://github.com/awslabs/lambda-refarch-mapreduce

Но у него, кажется, есть один главный недостаток - каждый раз, когда этап карты завершается, он записывает свои результаты на S3 (я в порядке с использованием этого как временного), затем запускает новую lambda через событие. Эта активированная лямбда смотрит, все ли были записаны на хранение. Если нет, это заканчивается, если да, то это делает шаг сокращения. Это похоже на справедливое решение, но я просто немного обеспокоен: а) опасностью гонки, когда два результата приходят вместе, могут ли два редуктора вычислить результаты? И б) похоже, что он увольняет много лямбда, которые все просто решили не запускать (я знаю, что они дешевы для запуска, но удвоение числа до двух на симуляцию - расчет и, возможно, сокращение - будет, очевидно, удвоить затраты). Есть ли способ отключить результат S3 после того, как, скажем, 100 файлов записаны в папку, а не после каждого?

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

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

Короче говоря, я хочу:

Запрос API → Вычислить результаты параллельно → Ответ API

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

Несколько вариантов, которые я вижу:

Используйте функцию шага, которая теперь поддерживается шлюзом AWS API, и вызывается несколько lambdas в одном состоянии, ожидая, пока все они вернутся до перехода.

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

Используйте фреймворк mapreduce или что-то подобное и найдите способ ответа на входящий запрос с другой лямбда на тот, который изначально был вызван запросом API. В идеале также уменьшите количество задействованных здесь событий S3, но это не приоритет.

Немедленно ответьте на исходный запрос API с первой лямбда, затем добавьте больше данных пользователю позже, когда закончите вычисления (они должны занимать около 30 секунд с parallelism, а домен таков, что это приемлемое время ожидания ответа, даже ответ HTTP).

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

Запрос → Mapreduce → Mapreduce → ... → Response

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

Спасибо.

P.S. Я не могу их создать, и теги aws-emr и aws-elastic-mapreduce пока не существуют.

4b9b3361

Ответ 1

Интересная ситуация.. Любимая информация о деталях проблемы. В принципе, мы ищем массу мощности процессора, но на короткое время... и должны быть доступны быстро. Основная проблема, если мы действительно осознаем лямбда, заключается в том, что она не делает 't поддерживает потоки и не поддерживает поведение async.

Подумайте над этим.. Лямбда выглядит правильным способом. Что делать, если вы пользуетесь dynamodb (не другим db, потому что требование очень мало, поэтому для получения другого экземпляра ec2 только для этого). Всякий раз, когда лямбда-функция завершает его и обновляет запись в dynamodb.. и если это значение в db более 100 → выполняет вашу окончательную лямбда-функцию.

Число, фиксированное в 100? или это может быть любое число. Если это может быть любое число n; то я могу думать о решении, чтобы справиться с этим тоже..

Решение вашей проблемы о том, что "вызов api произошел с lambda 0 и вам нужно ответить на это", заключается в том, что lambda 0 должен выглядеть примерно так:

for ( int i = 0 ; i < n ; i++){
   invoke processinglambda[i]; // each processingLambda process and updates 
                               // results in dynamodb
}
while (true) {
 (if work is done by ALL processing lambdas){
     //collate all data 
     return result;
   }

}

Итак, мы в основном пытаемся реализовать MapReduce с использованием вышеописанного дизайна. Lambda 0 является master node; который делегирует задания узлам лямбда 1..N... которые обрабатывают и продолжают обновлять результаты в dynamodb.. Мастер node; продолжайте запрашивать dynamodb, если работа выполняется всеми дочерними узлами. После выполнения; master node сопоставляет все данные и возвращает ответ.

Ответ 2

Одна идея заключалась бы в том, чтобы вызвать функцию Lambda (назовите ее "директором рабочего процесса" ) через API GW, затем напишите код в этой функции, чтобы напрямую вызвать функции шага (или что-то еще) и опросить состояние, чтобы в итоге вы могли синхронно реагировать на HTTP-запрос.

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

Асинхронная модель (я предполагаю, что в этом случае функция вызова шага непосредственно из API GW) будет работать в любом случае.

Изменить: извините, возможно, неправильно поняли ваши комментарии о шаговых функциях. Я думал, что синхронного способа вызова рабочего процесса шага нет и ждать конечного состояния, но из вашего комментария кажется, что его уже нет.

Позвольте мне быстро ответить на несколько ваших конкретных вопросов:

Есть ли способ отключить результат S3 после того, как, скажем, 100 файлов записаны в папку, а не после каждого?

Я считаю, что это невозможно.

Я не уверен, как запустить много лямбдов параллельно за один шаг, и все они возвратятся до перехода в состояние машины

Вы видели это в документах? http://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-parallel-state.html