この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
CX事業本部@大阪の岩田です。本日のアップデートにより、LambdaのランタイムでGraviton2 processorが利用可能になりました。
Lambdaの実行基盤で利用されているFirecrackerのロードマップを確認すると、2020年末ごろからArm CPUサポートがShipped
状態になっていたので、LambdaのGraviton2対応がそろそろ来そうかな?と予想していたのですが、満を持してGraviton2対応がGAされました。
https://github.com/firecracker-microvm/firecracker/projects/13
何がうれしいのか
Graviton ProcessorとはAWSがカスタムビルドしたARM ベースのプロセッサーで、ハイパフォーマンスかつ低コストで利用できるのが最大のメリットです。前述のAWSのアナウンスによると、Graviton2 processorベースのLambdaは従来のx86よりも20%低いコストで19%優れたパフォーマンスを発揮するように設計されているとのことです。
今回更新されたLambdaの料金体系から東京リージョンにおけるLambdaの実行時間あたりの料金を比較すると、Graviton2 processorは従来のx86と比較して以下の通り約20%のコストダウンとなります。
アーキテクチャ | 料金 |
---|---|
x86 | GB-秒あたり$0.0000166667 |
Arm(Graviton2 processor) | GB-秒あたり$0.0000133334 |
さらに、単純な実行時間あたりの課金削減に加えて、パフォーマンス向上による実行時間の削減にも期待できます。例えば、これまでx86で100ミリ秒かかっていた処理がGraviton2 processorで80ミリ秒で終わると仮定すると、20ミリ秒分の課金が削減できることになります。
すでにAWSのブログが公開されていますが、こちらのブログの検証パターンではGraviton2 processorにより
- 約30%の高速化
- 約44%のコスト削減
が実現できるようです
すでにEC2やRDSなどのサービスではGraviton Processor/Graviton2 processorを利用するインスタンスタイプが利用可能になっていましたが、今回のアップデートによりLambdaのランタイムでもGraviton2 processorが利用可能になりました。
Graviton2 processorは全てのランタイムで利用できるわけではなく、Amazon Linux2ベースのランタイムでのに利用できます。つまりPython3.7のようなAmazon LinuxベースのランタイムではGraviton2 processorは利用できません。また、すでにEnd of support phase 1を迎えているNode.js10でも同様にGraviton2 processorは利用できません。
具体的には現時点で
- Node.js 12 、 14
- Python 3.8 、 3.9
- Java 8 (
java8.al2
) 、 11 - .NET Core 3.1
- Ruby 2.7
- Custom Runtime(
provided.al2
)
がGraviton2 processorをサポートしています
試しにPython3.7のLambdaのアーキテクチャをarm64に更新してみたところ
Runtime python3.7 does not support the following architectures [arm64]. Please select different architectures from [x86_64, arm64] or select a different runtime.
というエラーが発生し、更新に失敗しました。
やってみる
実際にGraviton2 processorを利用するLambdaの動作を確認してみます
/proc/cpuinfoの確認
試しにLambdaのランタイムにNode.js 14.xを指定し、以下のコードを実行。
const execSync = require('child_process').execSync;
exports.handler = async (event) => {
const cmd = 'cat /proc/cpuinfo';
const result = execSync(cmd).toString();
console.log("\n"+result);
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
アーキテクチャに
- x86_64
- arm64
それぞれを指定した場合の出力を比較してみました。なお、Lambdaのメモリ割り当てはデフォルトの128Mとしています。
x86_64の場合の出力はこちら
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 63
model name : Intel(R) Xeon(R) Processor @ 2.50GHz
stepping : 2
microcode : 0x1
cpu MHz : 2500.008
cache size : 36608 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm cpuid_fault invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid smap xsaveopt arat md_clear arch_capabilities
bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs
bogomips : 5000.01
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 63
model name : Intel(R) Xeon(R) Processor @ 2.50GHz
stepping : 2
microcode : 0x1
cpu MHz : 2500.008
cache size : 36608 KB
physical id : 0
siblings : 2
core id : 1
cpu cores : 2
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm cpuid_fault invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid smap xsaveopt arat md_clear arch_capabilities
bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs
bogomips : 5000.01
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:
arm64(Graviton2 processorの場合)の出力はこちら
processor : 0
BogoMIPS : 243.75
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x3
CPU part : 0xd0c
CPU revision : 1
processor : 1
BogoMIPS : 243.75
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x3
CPU part : 0xd0c
CPU revision : 1
UnixBenchの比較
せっかくなので従来のx86環境とGraviton2環境を比較してみます。CPUのベンチマークといえばUnixBenchが定番ですね。Lambdaのパッケージ形式としてコンテナイメージを選択した場合もGraviton2 processorが利用できるので、UnixBenchが利用できるコンテナイメージを作成してLambda実行環境で動かしてみます。
まずDockerfileです
# x86向けのイメージのベース
FROM amazon/aws-lambda-provided:al2.2021.09.13.11
# Graviton2向け向けのイメージのベース
# FROM amazon/aws-lambda-provided:al2
RUN yum install -y git gcc make && \
git clone https://github.com/kdlucas/byte-unixbench.git && \
cd byte-unixbench/UnixBench/ && \
make
COPY bootstrap /var/runtime/
COPY bootstrap function.sh /var/task/
RUN chmod 755 /var/runtime/bootstrap /var/task/function.sh
CMD ["function.handler"]
ENV UB_RESULTDIR /tmp
ENV UB_TMPDIR /tmp
デプロイするLambdaの設定がx86かarm64(Graviton2 processor)かに応じてFROM
で指定するベースのイメージを切り替えて下さい
Dockerfile内でCOPYしているbootstrapです
#!/bin/sh
set -euo pipefail
# Initialization - load function handler
source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh"
# Processing
while true
do
HEADERS="$(mktemp)"
# Get an event. The HTTP request will block until one is received
EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
# Extract request ID by scraping response headers received above
REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
# Run the handler function from the script
RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA")
# Send the response
curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE"
done
続いてfunction.sh
#!/bin/bash
function handler() {
cd /var/task/byte-unixbench/UnixBench/
./Run -i 5 dhrystone whetstone execl pipe spawn
}
こちらがLambdaのハンドラーから呼び出されることになります。テスト実行対象として
- dhrystone
- whetstone
- execl
- pipe
- spawn
を指定しつつ、Lambdaの実行時間上限である15分以内に処理が完了するようにテスト回数を5に減らしています
あとはx86環境用とarm環境用それぞれのコンテナイメージをビルドしてECRにプッシュします
docker build -t cm-iwata/lambda-unixbench:x86_64 .
docker tag cm-iwata/lambda-unixbench:x86_64 <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-unixbench:x86_64
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com
docker push <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-unixbench:x86_64
プッシュできたら作成したコンテナイメージを参照するようにLambda関数を作成し、以下の設定を編集します
- メモリ(MB)...1792MB
- Lambdaはメモリ割当1.8Gから1vCpu分のフルパワーが利用できるようになります
- タイムアウト...15分
設定できたらテスト実行してUnixBenchの出力を確認しましょう。結果は以下の通りでした
結果(x86_64)
make all
make[1]: Entering directory `/var/task/byte-unixbench/UnixBench'
make distr
make[2]: Entering directory `/var/task/byte-unixbench/UnixBench'
Checking distribution of files
./pgms exists
./src exists
./testdir exists
./tmp exists
./results exists
make[2]: Leaving directory `/var/task/byte-unixbench/UnixBench'
make programs
make[2]: Entering directory `/var/task/byte-unixbench/UnixBench'
make[2]: Nothing to be done for `programs'.
make[2]: Leaving directory `/var/task/byte-unixbench/UnixBench'
make[1]: Leaving directory `/var/task/byte-unixbench/UnixBench'
# # # # # # # ##### ###### # # #### # #
# # ## # # # # # # # ## # # # # #
# # # # # # ## ##### ##### # # # # ######
# # # # # # ## # # # # # # # # #
# # # ## # # # # # # # ## # # # #
#### # # # # # ##### ###### # # #### # #
Version 5.1.3 Based on the Byte Magazine Unix Benchmark
Multi-CPU version Version 5 revisions by Ian Smith,
Sunnyvale, CA, USA
January 13, 2011 johantheghost at yahoo period com
------------------------------------------------------------------------------
Use directories for:
* File I/O tests (named fs***) = /tmp
* Results = /tmp
------------------------------------------------------------------------------
1 x Dhrystone 2 using register variables 1 2 3 4 5
1 x Double-Precision Whetstone 1 2 3 4 5
1 x Execl Throughput 1 2
1 x Pipe Throughput 1 2 3 4 5
1 x Process Creation 1 2
2 x Dhrystone 2 using register variables 1 2 3 4 5
2 x Double-Precision Whetstone 1 2 3 4 5
2 x Execl Throughput 1 2
2 x Pipe Throughput 1 2 3 4 5
2 x Process Creation 1 2
========================================================================
BYTE UNIX Benchmarks (Version 5.1.3)
System: : GNU/Linux
OS: GNU/Linux -- 4.14.243-194.434.amzn2.x86_64 -- #1 SMP Tue Aug 17 23:23:16 UTC 2021
Machine: x86_64 (x86_64)
Language: en_US.utf8 (charmap=\"UTF-8\", collate=\"UTF-8\")
CPU 0: Intel(R) Xeon(R) Processor @ 2.50GHz (5000.0 bogomips)
Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
CPU 1: Intel(R) Xeon(R) Processor @ 2.50GHz (5000.0 bogomips)
Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
; runlevel
------------------------------------------------------------------------
Benchmark Run: Thu Sep 30 2021 07:41:48 - 07:47:28
2 CPUs in system; running 1 parallel copy of tests
Dhrystone 2 using register variables 37534408.4 lps (10.0 s, 4 samples)
Double-Precision Whetstone 4859.5 MWIPS (9.9 s, 4 samples)
Execl Throughput 3928.1 lps (29.9 s, 2 samples)
Pipe Throughput 1517401.9 lps (10.0 s, 4 samples)
Process Creation 7633.7 lps (30.0 s, 2 samples)
System Benchmarks Partial Index BASELINE RESULT INDEX
Dhrystone 2 using register variables 116700.0 37534408.4 3216.3
Double-Precision Whetstone 55.0 4859.5 883.5
Execl Throughput 43.0 3928.1 913.5
Pipe Throughput 12440.0 1517401.9 1219.8
Process Creation 126.0 7633.7 605.8
========
System Benchmarks Index Score (Partial Only) 1139.2
------------------------------------------------------------------------
Benchmark Run: Thu Sep 30 2021 07:47:28 - 07:53:05
2 CPUs in system; running 2 parallel copies of tests
Dhrystone 2 using register variables 37851790.7 lps (10.0 s, 4 samples)
Double-Precision Whetstone 5320.4 MWIPS (9.2 s, 4 samples)
Execl Throughput 3462.3 lps (29.5 s, 2 samples)
Pipe Throughput 1537607.3 lps (10.0 s, 4 samples)
Process Creation 8282.3 lps (30.0 s, 2 samples)
System Benchmarks Partial Index BASELINE RESULT INDEX
Dhrystone 2 using register variables 116700.0 37851790.7 3243.5
Double-Precision Whetstone 55.0 5320.4 967.3
Execl Throughput 43.0 3462.3 805.2
Pipe Throughput 12440.0 1537607.3 1236.0
Process Creation 126.0 8282.3 657.3
========
System Benchmarks Index Score (Partial Only) 1154.7
結果(arm64)
make all
make[1]: Entering directory `/var/task/byte-unixbench/UnixBench'
make distr
make[2]: Entering directory `/var/task/byte-unixbench/UnixBench'
Checking distribution of files
./pgms exists
./src exists
./testdir exists
./tmp exists
./results exists
make[2]: Leaving directory `/var/task/byte-unixbench/UnixBench'
make programs
make[2]: Entering directory `/var/task/byte-unixbench/UnixBench'
make[2]: Nothing to be done for `programs'.
make[2]: Leaving directory `/var/task/byte-unixbench/UnixBench'
make[1]: Leaving directory `/var/task/byte-unixbench/UnixBench'
# # # # # # # ##### ###### # # #### # #
# # ## # # # # # # # ## # # # # #
# # # # # # ## ##### ##### # # # # ######
# # # # # # ## # # # # # # # # #
# # # ## # # # # # # # ## # # # #
#### # # # # # ##### ###### # # #### # #
Version 5.1.3 Based on the Byte Magazine Unix Benchmark
Multi-CPU version Version 5 revisions by Ian Smith,
Sunnyvale, CA, USA
January 13, 2011 johantheghost at yahoo period com
------------------------------------------------------------------------------
Use directories for:
* File I/O tests (named fs***) = /tmp
* Results = /tmp
------------------------------------------------------------------------------
1 x Dhrystone 2 using register variables 1 2 3 4 5
1 x Double-Precision Whetstone 1 2 3 4 5
1 x Execl Throughput 1 2
1 x Pipe Throughput 1 2 3 4 5
1 x Process Creation 1 2
2 x Dhrystone 2 using register variables 1 2 3 4 5
2 x Double-Precision Whetstone 1 2 3 4 5
2 x Execl Throughput 1 2
2 x Pipe Throughput 1 2 3 4 5
2 x Process Creation 1 2
========================================================================
BYTE UNIX Benchmarks (Version 5.1.3)
System: : GNU/Linux
OS: GNU/Linux -- 4.14.243-194.434.amzn2.aarch64 -- #1 SMP Tue Aug 17 23:22:56 UTC 2021
Machine: aarch64 (aarch64)
Language: en_US.utf8 (charmap=\"UTF-8\", collate=\"UTF-8\")
; runlevel
------------------------------------------------------------------------
Benchmark Run: Thu Sep 30 2021 06:40:31 - 06:46:08
2 CPUs in system; running 1 parallel copy of tests
Dhrystone 2 using register variables 41879150.0 lps (10.0 s, 4 samples)
Double-Precision Whetstone 5925.2 MWIPS (9.7 s, 4 samples)
Execl Throughput 5401.7 lps (30.0 s, 2 samples)
Pipe Throughput 1721879.1 lps (10.0 s, 4 samples)
Process Creation 9100.0 lps (30.0 s, 2 samples)
System Benchmarks Partial Index BASELINE RESULT INDEX
Dhrystone 2 using register variables 116700.0 41879150.0 3588.6
Double-Precision Whetstone 55.0 5925.2 1077.3
Execl Throughput 43.0 5401.7 1256.2
Pipe Throughput 12440.0 1721879.1 1384.1
Process Creation 126.0 9100.0 722.2
========
System Benchmarks Index Score (Partial Only) 1371.6
------------------------------------------------------------------------
Benchmark Run: Thu Sep 30 2021 06:46:08 - 06:51:51
2 CPUs in system; running 2 parallel copies of tests
Dhrystone 2 using register variables 42419526.5 lps (10.0 s, 4 samples)
Double-Precision Whetstone 6027.4 MWIPS (9.6 s, 4 samples)
Execl Throughput 4147.8 lps (29.6 s, 2 samples)
Pipe Throughput 1716980.9 lps (10.0 s, 4 samples)
Process Creation 8764.6 lps (30.0 s, 2 samples)
System Benchmarks Partial Index BASELINE RESULT INDEX
Dhrystone 2 using register variables 116700.0 42419526.5 3634.9
Double-Precision Whetstone 55.0 6027.4 1095.9
Execl Throughput 43.0 4147.8 964.6
Pipe Throughput 12440.0 1716980.9 1380.2
Process Creation 126.0 8764.6 695.6
========
System Benchmarks Index Score (Partial Only) 1298.3
今回はメモリの割当を1792MBで実行しているので、1並列でテストを実行した結果で比較するのが良さそうですね。スコアとしては
- x86...1139.2
- arm64(Graviton2)...1371.6
という結果でした。Lambda実行環境のデプロイ先としてどのハードウェアを引き当てるかというガチャ要素があるため、本来はもう少しテスト回数を重ねたいところではありますが、概ねカタログスペックである19%近くスコアがアップしていることが確認できました。
まとめ
Lambdaをバリバリ活用されているシステムでは
- 処理の高速化
- コスト削減
ともに期待できる非常にうれしいアップデートではないでしょうか?
既存のコードがそのまま正しく動作するかの検証は必要ですが、もしGraviton2 processorに移行できれば大きなメリットが享受できそうです。既存のワークロードをGraviton2 processorに移行できないか、是非一度検証してみて下さい。