我有一个程序可以执行数千个蒙特卡罗模拟来预测结果;我不能说他们真正预测的是什么,所以我将使用“圣诞老人无可争辩的存在”中的另一个例子,因为这些算法的内容与问题无关。我想知道大富翁板上每个方格的访问频率(以预测哪些是最好的房产)。为此,我模拟了数以千计的游戏并整理了结果。我当前的实现是一个独立的 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
存在。