Earth Engine は、大規模な計算を実行するための Google のツールとサービスを基盤として構築されています。大規模な地理空間分析を簡単に実行できるように、Earth Engine プラットフォームと API は、基盤となる並列処理インフラストラクチャの複雑さの多くを隠蔽しています。
EECU
概要
Earth Engine コンピューティング ユニット(EECU)は、瞬時の処理能力を表すメカニズムです。Earth Engine は、タスクの EECU 使用量の合計を時間(EECU 秒、EECU 時間など)の関数として追跡します。Google にはさまざまな種類のプロセッサ コアやアーキテクチャなどがあるため、 EECU はコンピューティング能力について説明する際に役立つ抽象化です。
目的
EE ユーザーは、ワークフローに必要な処理能力の量を推定したいことがよくあります。EECU は、比較を行うための整合性のある指標を提供します。
CPU 指標との比較
特定の結果を処理するマシンの数、タイプ、アーキテクチャは時間の経過とともに変化する可能性があります。物理コアごとにパフォーマンス特性が異なる可能性があるため、Earth Engine は EECU を使用してすべての処理を抽象化します。 EECU 時間(または EECU 時間の他の単位)は実時間に対応しないため、10 EECU 時間を消費するジョブの実行時間が数分になることがあります。
安定性と予測可能性
同じ(または類似の)リクエストを Earth Engine に送信すると、計算量が大きく異なることがあります。違いが生じる一般的な要因は次のとおりです。
- 以前の計算の結果( 部分的な結果や中間結果を含む)の再利用などのキャッシュ保存
- 基盤となるデータの違い(衛星画像の数、 複雑さの異なるジオメトリなど)
- パフォーマンスの最適化、バグ修正など、EE プラットフォームでのアルゴリズムの変更
- クライアント ライブラリの変更(特に、他のユーザーの EE コードやパッケージに依存している場合)
ベンチマーク
Earth Engine の計算のベンチマークのサンプルをご覧ください。
失敗したリクエストの指標
Earth Engine は、失敗したリクエストやタスクのパフォーマンス指標を提供しません。これらの数値は不正確または誤解を招く可能性があるためです。たとえば、ワーカー タスクが応答しなくなったためにジョブが失敗した場合、そのワーカーの処理消費量を合計に含めることはできません。
Profiler
プロファイラは、有効になっている間に実行された計算の結果として生じる EECU 時間とメモリ使用量(アルゴリズムごと、アセットごと)に関する情報を提供します。プロファイラの出力の各行は、[説明] 列に記載されているように、アルゴリズム、計算、アセットの読み込み、オーバーヘッド オペレーションに対応しています。プロファイラの列は次のとおりです。
- 説明
- プロファイリング対象の計算、アルゴリズム、アセットの読み込み、オーバーヘッド オペレーションの説明。
- カウント
- [説明] に記載されているオペレーションが呼び出された回数に比例する指標。
- コンピューティング
- オペレーションで費やされた EECU 時間の指標。
- 現在のメモリ量
この列は、スクリプト
が使用するメモリが多すぎるためにエラーが発生した場合にのみ表示されます。エラーが発生した時点で、単一のコンピューティング ノードで使用されているメモリの量が表示されます。
- ピークメモリ
オペレーションで単一のコンピューティング ノードで使用された最大メモリ。
プロファイラの有効化
コードエディタ
Python
プロファイラを有効にするには、Python スクリプトに次のコードを追加します。
with ee.profilePrinting():
print(ee.Number(3.14).add(0.00159).getInfo())
プロファイルは、コンテキスト内でエラーが発生したかどうかに関係なく、コンテキストが終了すると出力されます。
プロファイルを文字列としてキャプチャするには、プロファイルを文字列バッファに書き込みます。
import io
out = io.StringIO()
with ee.profilePrinting(destination=out) as p:
print(ee.Number(3.14).add(0.00159).getInfo())
print('Output:')
print(out.getvalue())
プロファイル文字列をテーブルに変換して、Colab と Jupyter ノートブックで簡単に分析できるようにする方法を次に示します(これは 1 つの方法にすぎず、すべてのケースに適しているとは限りません)。
import re
import pandas as pd
lines = out.getvalue().split('\n')
column_names = re.split(r'\s{1,}', lines[0])
column_names = [name.strip() for name in column_names if name.strip()]
data = [
[element for element in re.split(r'\s{2,}', line) if element.strip()]
for line in lines[1:-1]
]
df = pd.DataFrame(data, columns=column_names)
display(df)