13

我有一个程序可以执行数千个蒙特卡罗模拟来预测结果;我不能说他们真正预测的是什么,所以我将使用“圣诞老人无可争辩的存在”中的另一个例子,因为这些算法的内容与问题无关。我想知道大富翁板上每个方格的访问频率(以预测哪些是最好的房产)。为此,我模拟了数以千计的游戏并整理了结果。我当前的实现是一个独立的 C# 应用程序,但我想将它移动到云中,以便我可以将其作为服务提供 - 每个用户都可以通过提交他们每个骰子的面数来获得个性化的结果。

当前的实现也很慢 - 它非常具有并行性,因为每个模拟都是完全独立的,但我只有 8 个内核,因此在我的本地机器上完成大约 50000 个单独的模拟需要 20 分钟以上的时间。

计划是让 AWS lambda 函数每个运行一个(或多个)模拟,然后进行整理——基本上是 mapreduce。我考虑使用 AWS EMR(Elastic MapReduce),但这对于我想要的来说太大了,旋转实例以单独运行计算似乎比单独的整个计算花费更长的时间(这对于多小时离线分析,但我希望通过 Web 请求以低延迟响应)。

我认为理想的情况是:

Lambda 0 - 触发许多其他 lambda 函数,每个函数只进行一小部分计算。Lambda 1..N - 并行进行许多模拟(数字不是常数)。Lambda N+1 - 整理所有结果并返回答案。

这里有一个 lambda mapreduce 框架:

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

但它似乎有一个主要缺点 - 每次映射阶段完成时,它都会将其结果写入 S3(我可以将其用作临时),然后通过事件触发新的 lambda。触发的 lambda 查看是否所有结果都已写入存储。如果不是,则结束,如果是,则执行还原步骤。这似乎是一个公平的解决方案,但我只是有点担心 a) 当两个结果一起出现时的竞争风险,两个 reducer 可以同时计算结果吗?并且 b) 似乎它正在触发很多 lambdas,所有这些 lambdas 都只是决定不运行(我知道它们运行起来很便宜,但是每次模拟将数字加倍到两个 - 计算并可能减少 - 显然会使成本加倍)。有没有办法在将 100 个文件写入文件夹而不是每个文件之后触发 S3 结果?

我研究了使用步进函数,但我不确定如何一步并行触发许多 lambda,并在状态机转换之前让它们全部返回。然而,步进函数对最终的皱纹很有用 - 我想将所有这些隐藏在 API 后面。

根据我的阅读,API 可以触发 lambda 并返回该 lambda 的结果,但我不希望调用的 lambda 成为返回结果的那个。相反,当您从 API 调用 step 函数时,API 调用会返回最后一个状态的结果。

简而言之,我想要:

API 请求 -> 并行计算结果 -> API 响应

中间的那一点我不清楚该怎么做,同时能够返回所有结果作为对原始请求的响应——无论是靠自己还是很容易。

我可以看到一些选项:

使用 AWS API 网关现在原生支持的 step 函数,并在一个状态下调用多个 lambda,等待它们全部返回,然后再进行转换。

使用 AWS EMR,但以某种方式保持预置实例始终处于活动状态以避免预置时间开销。这显然否定了 Lambda 的可扩展性,而且成本更高。

使用 mapreduce 框架或类似的框架,并找到一种方法来响应来自与 API 请求最初调用的不同 lambda 的传入请求。理想情况下,还可以减少此处涉及的 S3 事件的数量,但这不是优先事项。

立即响应来自第一个 lambda 的原始 API 请求,然后在计算完成后将更多数据推送给用户(它们应该只需要大约 30 秒的并行性,并且域是可以接受的等待时间响应,甚至是 HTTP 响应)。

我怀疑它会对解决方案产生任何影响,因为它只是中间位的扩展,而不是根本性的变化,但真正的计算是迭代的,所以是:

请求 -> Mapreduce -> Mapreduce -> ... -> 响应

只要我知道如何在请求中链接一组 lambda 函数,链接更多应该是相同的(我希望)。

谢谢你。

PS我无法创建它们,标签aws-emr也不aws-elastic-mapreduce存在。

4

2 回答 2

2

一种想法是通过 API GW 调用一个 Lambda 函数(称之为“工作流程主管”),然后在该函数中编写代码以直接调用步骤函数(或其他)并轮询状态,以便最终同步响应 HTTP 请求.

这只是异步工作流程的同步包装器。请记住,API GW 有 29 秒的硬超时,因此如果您预计此工作流程将花费大约 30 秒,那么实施同步版本可能不值得。

异步模型(我猜在这种情况下直接从 API GW 调用 step 函数)在任何一种情况下都可以工作。

编辑:抱歉,可能误解了您对阶跃函数的评论。我认为没有同步方式来调用步骤函数工作流并等待最终状态,但从您的评论看来,似乎已经存在。

让我快速回答您的几个具体问题:

有没有办法在将 100 个文件写入文件夹而不是每个文件之后触发 S3 结果?

我相信这是不可能的。

我不确定如何一步并行触发多个 lambda,并在状态机转换之前让它们全部返回

您在文档中看到了吗?http://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-parallel-state.html

于 2017-08-07T19:38:44.050 回答
1

有趣的情况.. 喜欢阅读问题的详细信息.. 基本上,我们正在寻找 CPU 功率负载,但持续时间很短......并且应该很快可用......如果我们真正意识到 lambda 的基本问题是它不支持线程并且不支持异步行为。

仔细考虑一下.. Lambda 看起来是正确的方法.. 如果您借助 dynamodb 会怎样(不是另一个 db,因为要求非常小;为什么要为此设置另一个 ec2 实例).. 每当 lambda 函数完成时,它都会执行并更新 dynamodb 中的记录 .. 如果 db 中的这个值大于 100 --> 执行你的最终 lambda 函数..

数字是固定在 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 是主节点;它将作业委托给节点 lambda 1..N... 进行处理并不断更新 dynamodb .. 主节点中的结果;如果所有子节点都完成了工作,请继续查询 dynamodb。一旦完成;主节点整理所有数据并返回响应。

于 2017-08-09T08:55:07.177 回答