- 公開日
- 最終更新日
Lambdaを1000個同時起動して円周率を求めてみよう(モンテカルロ法)
この記事を共有する
目次
はじめに
パーソル&サーバーワークスの横山です。
今回は円周率っていくつだっけ?と思ったのでそれを解決するための検証を行いました。
AWS Lambda(以下Lambda)の同時実行数は、1アカウント・1リージョンあたりデフォルトで1000個です。
よって上限まで使って円周率を計算することに致します。
円周率の求め方
円周÷直径
モンテカルロ法を利用して円周率を求めます。
- ①1辺が1の正方形の中に、半径1の円の1/4を描き、正方形の中にランダムに点を打つ。
- ②全プロット数に対する円の内部のプロット数の割合を求める。
- ③その割合を4倍することで、円周率の近似値が得られる。
ゴール
- Lambda大量並列でモンテカルロ法を実装する
- Fan-out / Fan-in をStep Functionsで制御
構成
シンプルにAWS Step Functions(以下Step Functions)を実行し、そこからLambdaを叩くような構成にします。
当然全てサーバーレスアーキテクチャとなります。円周率を求めるためにEC2インスタンス+RDSのような構成は無駄としか言えません。
概算
Lambda1台あたり、512MBの最小スペックを利用します。
ArmベースだとGB-秒あたり USD 0.0000133334なので
1000(Woker)×0.0000133334×0.5(GB)=0.0066667ドル、
つまり1分の利用で0.4ドル、5分で2ドルくらいと概算しましょうか。
Step Functionsは4000回の遷移が無料枠の範囲内であるため、1回の実行で1ドルもあれば充分な気もします。
実際にやってみた
作成したコードは別途添付しますのでこちらでは動作の流れを見ていただきたいと思います。
Step Funcsionsにより只管Woker用のLambdaが繰り返し実行されている様子が見えます。

結果
実行したiteration 数が1000となっているため1000Wokerを並列実行出来たことがわかります。
求められた値も「3.14168272」とまあ大体あってます。
3.14を習う小中学生くらいであればLambdaによるモンテカルロ法は有効であると言えるのではないでしょうか?
25秒の実行のため0.1666675ドルなので日本円にして26円程度(※2026/2/3時点での円換算レート 1ドル155.46円をベースに計算しています)小学生の駄菓子代と同程度でしょうか?
利用したLambdaコード
Lambda-Stack-worker
import random
def handler(event, context):
n = int(event.get("points", 0))
hit = 0
for _ in range(n):
x = random.random()
y = random.random()
if x*x + y*y <= 1:
hit += 1
return {"hit": hit, "total": n}
Lambda-Stack-aggregator
def handler(event, context):
items = event
normalized = []
if isinstance(items, list):
for it in items:
if isinstance(it, dict) and "Payload" in it and isinstance(it["Payload"], dict):
normalized.append(it["Payload"])
else:
normalized.append(it)
else:
normalized = []
total_hit = sum(int(r.get("hit", 0)) for r in normalized if isinstance(r, dict))
total_points = sum(int(r.get("total", 0)) for r in normalized if isinstance(r, dict))
pi = 4 * total_hit / total_points if total_points else None
print("workers:", len(normalized))
print("total_hit:", total_hit)
print("total_points:", total_points)
print("pi:", pi)
return {"pi": pi, "total_hit": total_hit, "total_points": total_points, "workers": len(normalized)}
Step Funcsionの定義
{
"Comment": "Monte Carlo Pi via Map State fan-out/fan-in",
"StartAt": "Prepare",
"States": {
"Prepare": {
"Type": "Pass",
"Parameters": {
"workers.$": "States.ArrayRange(1, 1000, 1)",
"points_per_worker": 100000
},
"Next": "FanOut"
},
"FanOut": {
"Type": "Map",
"ItemsPath": "$.workers",
"MaxConcurrency": 1000,
"Parameters": {
"points.$": "$.points_per_worker"
},
"Iterator": {
"StartAt": "Worker",
"States": {
"Worker": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "arn:aws:lambda:ap-northeast-1:<アカウントID>:function:Lambda-Stack-worker",
"Payload.$": "$"
},
"OutputPath": "$.Payload",
"End": true
}
}
},
"Next": "Aggregate"
},
"Aggregate": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "arn:aws:lambda:ap-northeast-1:<アカウントID>:function:Lambda-Stack-aggregator",
"Payload.$": "$"
},
"OutputPath": "$.Payload",
"End": true
}
}
}
まとめ
あれ・・・3.14の次ってなんだっけ・・・となった際に使えるコードと構成になったかと思います。
ただ読者の方が3.141と暗記するだけで1回あたり1ドルをかけて計算する必要はなくなります。
また恐らくこのブログを見ている人はGoogleに円周率を聞いたほうが安く円周率を教えてくれる可能性があります。
この記事は私が書きました
横山 俊成
記事一覧こんにちは!サービスGの横山です。 オンプレ/クラウド問わずインフラエンジニアとしてキャリアを積んできました。 「面倒なことは自動化したい」という精神のもと、効率的なインフラ構築・運用を目指しています。 趣味は ゲームです。夢は会社でポケモンユナイトのチームを組んで企業リーグに出場し優勝すること 「どうすればもっと楽ができるか?」を常に考えながら、日々技術を磨いています! よろしくお願いします! 🚀