本記事の内容は2025/12/21時点の情報で書かれています。
要旨
- Lambda関数でArmを指定し関数を実行した際に、実行基盤のCPU partが"0xd40"と表示されることがある。この値はGraviton3の使用と推測できる
- 同条件でも別デプロイ時にはCPU partの値は"0xd0c"と表示され、こちらはGraviton2の情報と合致する
- 複数リージョンで複数回デプロイを行ったところ、一定の割合でGraviton2とGraviton3か混在している結果が確認され、割合はリージョンによって異なった
公開されているドキュメントなどを検索しましたが、Lambdaの実行環境にgraviton3が利用されているとの記載は見つけられませんでした。
情報お持ちの方いましたら共有いただけると幸いです。mm
※ECS FargateのArmで実行した際のCPUについてGraviton3が利用されているとの検証は以下ポストなどを参照のこと。
https://x.com/GedowFather/status/1976091964169912532?s=20
2025/12/24追記
LambdaとECS Fargateについては以下で共にFirecrackerが利用しているため、類似の構成になる可能性も高そうです。
https://aws.amazon.com/jp/blogs/opensource/firecracker-open-source-secure-fast-microvm-serverless/
@RubiconLinkさんご指摘ありがとうございました。
経緯
Lambda マネージドインスタンスが発表されたタイミングだったのでGraviton4でLambdaが実行できそうだなー、通常のLambdaはGraviton2で実行されているはずだから性能の比較検証してみるか、と思い準備を進めていました。
まずは現在のGraviton2の性能を確認してみようと思い、Lambdaの実行環境情報を取得してみたところ、デプロイごとにcpu_partの値が変わっていそうなことを確認しました。予想外。
具体的には"0xD0C"または"0xD40"の値が返ってきていました。
東京リージョンでの実行です。
実行コードは以下です。
Pythonコード
import json
def lambda_handler(event, context):
cpu_part = None
try:
with open("/proc/cpuinfo", "r") as f:
for line in f:
if line.startswith("CPU part"):
cpu_part = line.split(":")[1].strip()
break
except Exception:
pass
return {
"statusCode": 200,
"body": json.dumps({"cpu_part": cpu_part})
}
この値はlinuxのカーネルのarch/arm64/include/asm/cputype.h内に記載を参考すると以下のよう名称に対応するようです。
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C
#define ARM_CPU_PART_NEOVERSE_V1 0xD40
また、Gravitonで利用されているCPUについては、Black-Beltの資料の15スライド目に以下のような記載がありました。
Graviton2:Core:Neoverse-N1
Graviton3:Core:Neoverse-V1
上記をまとめて対応表にすると以下のようになります。
| CPU part | CPU | Graviton |
|---|---|---|
| "0xd0c" | NEOVERSE_N1 | Graviton2 |
| "0xd40" | NEOVERSE_V1 | Graviton3 |
どうやらGraviton2と3が混在してそうです。
ドキュメントなどを探してみましたがGraviton2を採用との記載は見つけられましたが、Graviton3については情報が見つからず。。。
ついでなので混在の割合とリージョンごとの違いがあるかについて追加で調べてみました。
リージョン別割合検証
ap-northeast-1での検証だとデプロイごとにCPU Partが混在していたので、追加のリージョンも含めて検証をしてみました。
前述のLambda関数をap-northeast-1、ap-northeast-3、ap-southeast-1、us-east-1、us-west-2、eu-west-1で再デプロイ+関数実行を100回実行し、cpu_partの値を確認しました。
ちなみに再デプロイなしで連続実行するwarm startではcpu_partの値は変化しませんでした。
今回は全てMemory:128MBで検証しています。
拡張した場合には異なる割合になる可能性も考えられます。
その結果が以下です。(2025/12/21実行)
| リージョン | Graviton2 (0xd0c) | Graviton3? (0xd40) |
|---|---|---|
| ap-northeast-1 (Tokyo) | 57% | 43% |
| ap-northeast-3 (Osaka) | 98% | 2% |
| ap-southeast-1 (Singapore) | 55% | 45% |
| us-east-1 (N. Virginia) | 26% | 74% |
| us-west-2 (Oregon) | 21% | 79% |
| eu-west-1 (Ireland) | 43% | 57% |
上記を見ると、大まかに地域ごとに実行割合が違いそうです。
米国の主要リージョンでは7~8割、アジアでは5割の割合でGraviton3らしき値が返ってきました。
ただし大阪ではほぼ100%Graviton2。なんでや。
参考:処理速度検証
処理能力にも差が出そうだなということで、Geminiに処理時間を測れるようなコードを書いてもらい、処理速度を確認してみました。
bench.py
import json
import time
EXECUTION_COUNT = 20
def get_cpu_part():
"""CPU part を取得"""
try:
with open("/proc/cpuinfo", "r") as f:
for line in f:
if line.startswith("CPU part"):
return line.split(":")[1].strip()
except:
pass
return None
def benchmark_prime(n=10000):
"""素数計算ベンチマーク: 1〜n の素数をカウント"""
count = 0
for num in range(2, n + 1):
is_prime = True
for i in range(2, int(num ** 0.5) + 1):
if num % i == 0:
is_prime = False
break
if is_prime:
count += 1
return count
def benchmark_matrix(size=100):
"""行列乗算ベンチマーク: size x size 行列の乗算"""
# 行列 A, B を作成
A = [[i + j for j in range(size)] for i in range(size)]
B = [[i * j for j in range(size)] for i in range(size)]
# 行列乗算 C = A * B
C = [[0] * size for _ in range(size)]
for i in range(size):
for j in range(size):
for k in range(size):
C[i][j] += A[i][k] * B[k][j]
return C[0][0] # 結果の一部を返す
def lambda_handler(event, context):
# CPU part 取得
cpu_part = get_cpu_part()
# 素数計算ベンチマーク
start = time.perf_counter()
prime_count = benchmark_prime(10000)
prime_time_ms = (time.perf_counter() - start) * 1000
# 行列乗算ベンチマーク
start = time.perf_counter()
matrix_result = benchmark_matrix(100)
matrix_time_ms = (time.perf_counter() - start) * 1000
total_time_ms = prime_time_ms + matrix_time_ms
result = {
"execution_count": EXECUTION_COUNT,
"cpu_part": cpu_part,
"prime_count": prime_count,
"prime_time_ms": round(prime_time_ms, 2),
"matrix_time_ms": round(matrix_time_ms, 2),
"total_time_ms": round(total_time_ms, 2)
}
return {
"statusCode": 200,
"body": json.dumps(result)
}
以下はus-east-1で20回実行した実行結果です。
| リージョン | cpu_part | 割合 | 素数計算 | 行列演算 | 合計 |
|---|---|---|---|---|---|
| us-east-1 | 0xd40 (Graviton3?) | 17/20 (85%) | 18.82ms | 1391.66ms | 1410.48ms |
| us-east-1 | 0xd0c (Graviton2) | 3/20 (15%) | 50.47ms | 1794.40ms | 1844.88ms |
処理内容によって差はあると思いますが、今回は25%ほど処理速度が向上しています。
以下の公式の記事でもGraviton3は2に比べて"25%高いパフォーマンス"とあるので、手法としてもそれほどずれてはいないかなと思います。
当社の次世代 Graviton3 プロセッサは、Graviton2 プロセッサと比較して、最先端の DDR5 メモリテクノロジーに基づいて、最大 25 % 高いパフォーマンス、最大 2 倍の浮動小数点パフォーマンス、50% 高速なメモリアクセスを実現します。
まとめ
Lambda(Arm)の実行時にもECS Fargateと同様にGravitonガチャ要素がありそうです。
あまりないユースケースかもしれませんが実行時間がシビアなものは実行リージョンを選ぶなどの調整が必要かもしれませんね。
そもそも、Lambdaは実行時間に対しても課金されるので、ヘビーなユースケースであれば米国のリージョンを選ぶことで処理時間が減少し、コストが安くなる可能性もありそうです。
今は過渡期で最終的にはLambdaでのGravitonは最新化されていく流れなのかもしれませんが、シビアにコストパフォーマンスを考える場合は定期的に実行環境をモニタリングするのもありかもしれません。