Microsoft Fabric Spark のジョブ同時実行数の考察と検証【古い状態での挙動が含まれています】

## はじめに

Synapse Data Engineering を活用するうえで、Spark ジョブの同時実行数の記載を読み解いて検証しました。



2024/04/19追記

以下2点の拡充により、ジョブ同時実行は大幅に緩和されました。（本記事は古い情報となり、検証方法や、考え方の参考レベルとなります

https://blog.fabric.microsoft.com/ja-JP/blog/introducing-job-queueing-for-notebook-in-microsoft-fabric/

https://blog.fabric.microsoft.com/ja-jp/blog/introducing-optimistic-job-admission-for-fabric-spark?ft=All

注意：以下は2024/01時点の情報です。

### Spark ジョブについて

Spark ジョブは以下を対象にして検証します。

- Notebook の対話型セッション
- データパイプラインから実行するNotebook 実行タスク


## 参考ドキュメント

- [Fabric Spark のコンカレンシー制限とキューイング - Microsoft Fabric | Microsoft Learn](https://learn.microsoft.com/ja-jp/fabric/data-engineering/spark-job-concurrency-and-queueing)


## 前提知識

### Microsoft Fabric における Spark ジョブ

冒頭で申し上げたように、この記事ではジョブとは対話型セッションとパイプラインの実行と位置付けていますが、これは監視ハブから確認するとわかりやすいです。

Notebook の対話型セッションは、 Notebook の画面でセッションが起動中にジョブとして認識されます。

ノートブックの画面で、コードセルを実行するとセッションの確立が実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a4400c60-ab6e-df82-73ab-f6c109d7947e.png)

セッションが確立すると通知が表示され

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/19077892-239e-d26b-f261-24d8a0626e95.png)

セッションの準備が完了し、ノートブックのコマンドが実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/aaf6de80-75e0-e747-344b-3856507c78b2.png)

監視ハブからは、進行中のジョブとしてノートブックセッションが認識されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/f7a6b300-6df2-b45b-f6e9-d3d5cde1657c.png)

詳細を見るとランタイム情報などが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/c4ef48ee-9aa0-75d5-4c08-9b1edf273dfd.png)

セッションを停止すると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/c5d3cdb3-8828-a9b1-1018-378d827f3d30.png)

監視ハブからもジョブの状態が進行中から完了になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2af10323-5183-920b-4450-7ea79d8ee58b.png)

一方データパイプラインのNotebook アクティビティの実行も一つのジョブです。

このような、並列で動作する二つのNotebook アクティビティを構成した場合、2つのジョブが同時に送信されることになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2007ea38-d2b3-738c-2992-3b42deae1ee6.png)

実行時に監視ハブはこのような状態になり、2つジョブが認識されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/438486d6-d1cb-66c7-e64e-074fdd0241eb.png)


### スタータープールとカスタムプール

Fabric では既定で Spark を数秒の起動で利用できるスタータープールがあります。

[Fabric Spark でスターター プールを構成して管理します。 - Microsoft Fabric | Microsoft Learn](https://learn.microsoft.com/ja-jp/fabric/data-engineering/configure-starter-pools)

ワークスペースを作成した時点のFabric 容量 SKU で、最大ノード数が決まります（既定のノード数列を参照）が、1 ノードのサイズ＝ Spark 仮想コア数は固定で Medium = 8コアです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/587201cf-1d74-62f8-376c-d725dd218ec8.png)

たとえば、試用版では既定の最大ノードが 10 なので、スタータープールを利用したジョブは 80 コアを消費します。

以下の画像のようにワークスペースの設定からノード数は変更が可能ですが、ノードサイズは Medium で固定であることがわかります。また、この構成は1ジョブあたり、8 コアを消費する構成であることもわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/9285aa11-af1a-433b-2b25-c65a84dc20f2.png)


一方、カスタムプールではこの構成が自由ですが、起動時間は数分必要です。

[Fabric でカスタム Apache Spark プールを作成する - Microsoft Fabric | Microsoft Learn](https://learn.microsoft.com/ja-jp/fabric/data-engineering/create-custom-spark-pools)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/9ec57471-cdae-fb92-aab6-626163939099.png)

つまり、使用する Spark Pool の構成によって、Spark 仮想コアの消費数が大きく違う点を理解する必要があります。

補足：[ノードのサイズ](https://learn.microsoft.com/ja-jp/fabric/data-engineering/spark-compute#node-sizes)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/bafb05a3-26f2-9c81-6beb-f2f46a979345.png)


## SKU と Spark 仮想コア、キューの関係

SKUにより同時に使用できるSpark仮想コアとキューの数（同時に実行できジョブ数）が決まります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/fd19d722-6d1d-adcb-e653-a9650d0f1ad9.png)

表の通り、F2 容量では、Spark 仮想コアを4コア/秒が使えます。さらに、バーストという機能により、一時的に3倍の同時実行が可能です。以下のように、バーストはジョブの同時実行に寄与するものであり、1つのジョブを増強させられるわけではないことをご注意ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/30844070-88ee-0d39-7493-808540061f8a.png)

例：
- 〇: F64 環境では、Starter Pool Max 5 ノード構成(40 Spark コア消費)のジョブを9つ同時に実行できる
- -  1ジョブあたり80-> 128 未満と、F64の提供する仮想コア内であるためOK
- - 9ジョブ同時送信により40*9=360 だが、バーストにより合計消費コア数は384まで拡張されているため、同時実行可能
- ×：F64 環境では、Starter Pool Max 20 ノード構成(160 Spark コア消費)のジョブを1つ同時に実行できる。
- - F64 で構成できるのは、128コアまでであるためそもそも構成不可。バーストは寄与しない


## 検証

### F64環境で、40 コア消費するジョブをデータパイプラインで9つ同時実行

先ほどの例で挙げたケースを実際にやってみます。

まず、ワークスペース設定を以下のようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/ece0b509-ea4a-d332-be49-3e18ad3233e2.png)


パイプラインはこんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/00b9a6d4-0fa1-9464-e108-9cb1964d7ace.png)


実行結果は以下の通り。同時実行すべてが成功します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/bc26df61-1889-acae-fcb1-9fd4e095d81c.png)




### F64環境で、40 コア消費ジョブをデータパイプラインで10同時実行

では、1つ増やすとどうでしょうか。資産では、40*10=400でバースト係数を使用した最大 Spark 仮想コア数:384を超えるはずです。

パイプラインはアクティビティが10個並びました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/40e2471c-1542-368a-470f-137b34ffbfa7.png)

実行結果は以下のように、1つのジョブが失敗しています。ちなみにこのジョブは進行中にもなりませんでした。リクエスト時点で弾かれたということですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/6e2d385d-b5d1-a6fd-c2de-5de0c1fe3001.png)

エラーメッセージを見ると、最大のコア数を超えたことを示すHTTP 状態コード 430 が出力され、容量の上限を超えた旨が記載されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d3106a42-141b-5bc6-8fe5-3214a640427b.png)

### F64 環境で、80コア消費するNotebook の対話型セッションを5つ同時に起動していく

ワークスペース設定を以下のように変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/22273f9b-1121-0026-ec3d-06b8ea005f0f.png)

この状態でまずは一つ目：成功

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/bc3ef080-8ce2-b62a-0941-14fd55e651f1.png)


2～4つ目

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/57f45be2-8dbe-4c1f-ef6f-0dc58d97f8df.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/56667d61-0213-cbb6-3007-76737a699059.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/5a70b020-a33b-1fb2-15da-688b71b70c00.png)

ここまでで、ジョブは4つ進行中になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/b42d1f4c-ab63-ec10-abf6-01a78b175d11.png)

5つ目で想定通り失敗しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/ca41df1b-8911-aa43-1221-811fac70c144.png)

## まとめ

Spark ジョブの同時実行数はSKUと Spark Pool の構成により大きく幅が変わることがわかりました。特にSPark Pool の構成は試用版=F64という大きな環境でも既定で80コア確保されるような設定になっています。

Notebook開発者、パイプラインによるノートブックアクティビティの実行は同時にどれだけ実行されるのかに気を付けて、ワークスペース設定を構成してあげることで、余分なSpark 仮想コアを消費しないように気を付けましょう。

## 補足

最後の検証で、一人の開発者が複数のノートブックを開発する際に、このような制限がかかるのは厳しいという印象があるかもしれませんが、その場合には高コンカレンシーモードを使うことで、同じノートブックセッションを複数のノートブックで使いまわすことができます。これにより、制限に抵触しないで複数のノートブック実行を開発できますね。こちらの利用についてはまたの機会に

[Fabric Spark コンピューティングでの高コンカレンシー モード - Microsoft Fabric | Microsoft Learn](https://learn.microsoft.com/ja-jp/fabric/data-engineering/high-concurrency-overview)