0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ESP32 S3 memory bandwidthやCacheの仕組みについて

0
Posted at

ESP32-S3 のメモリ性能を本気で測る: PSRAM / GDMA / Cache prefetch の実測値

はじめに

ESP32-S3 の性能上限は CPU クロックだけでなく PSRAM / MSPI 帯域にも左右されることがあります。Octal DDR 120 MHz は理論 240 MB/s ですが、実用上限は 55% 程度にとどまるケースが多く、datasheet の理論値だけで設計すると見積もりを外しやすい印象です。

この記事では レイテンシ / 帯域 / Cache 活用 の観点で、ESP32-S3 のメモリサブシステムを実測します。ターゲットは ESP32-S3-WROOM-1 (PSRAM 8 MB)、ESP-IDF 5.3、PSRAM Octal 120 MHz、Cache line 64 B。

TL;DR

CPU からの PSRAM read

条件 帯域 [MB/s]
L1 D-cache (32 KB) に収まる seq read 239
cache を超える seq read 124.8 (MSPI 律速)
ランダムアクセス (4 MB) 8.2 (レイテンシ律速)

DMA (PSRAM → 内蔵 DRAM, M2M)

方法 起動コスト 256 KB スループット [MB/s]
esp_async_memcpy 約 12 ms ~17
raw GDMA (descriptor 再利用) 約 4 us 79.8

固定オーバヘッドが乗るので、esp_async_memcpy は小転送には不向き。1 KB を運ぶと実効 0.08 MB/s 程度にとどまり、raw GDMA なら ~60 MB/s 出る、というオーダ感。

MSPI バスの競合

シナリオ CPU 帯域 [MB/s] DMA 帯域 [MB/s] 合計 [MB/s]
CPUのみ 124.8 124.8
DMAのみ 1ch 79.7 79.7
CPU + DMA 1ch (並走) 67.4 (-46%) 65.8 (-17%) 133.2
CPU + DMA 2ch (並走) 67.3 66.0 133.3
  • 並走時は DMA が優先される挙動。CPU の cache fill 帯域は半分程度に落ちる傾向で、DMA 側の落ち込みは小さい。
  • MSPI 実用上限はおおむね ~133 MB/s 付近。本ベンチでは 2ch にしても大きくは超えなかった。

設計指針

  • 重い streaming は MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA の内蔵 DRAM に逃がす (cache バイパス、両コア coherent、msync 不要)
  • L1 D-cache (32 KB) は別用途に温存
  • PSRAM seq read は cache に収まる単位 (≤32 KB) でブロック化すると、本ベンチでは 2 倍程度の差が出た

環境

CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_120M=y
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000   # 32 KB shared L1 D-cache

計測は esp_timer_get_time() (1 us 解像度)、各サイズ 8 回平均。

実験 1: PSRAM の素の帯域とレイテンシ

for (i=0;i<n;i++) s += buf[i]; で測定。

アクセスパターン サイズ 帯域 [MB/s]
seq read (cache 内) 16 KB 239
seq read (MSPI 律速) 4 MB 124.8
memcpy PSRAM→DRAM 256 KB 126
random read 4 MB 8.2
  • cache hit vs miss で約 2x。
  • random read は 1 read あたり ~120 ns の MSPI レイテンシが律速で 8 MB/s。
  • 理論 240 MB/s に対し cache miss seq でも 52% (transaction overhead)。

Cache line 32 B → 64 B のトレードオフ

デフォルトの 32 B cache line では seq read が 83 MB/s 止まり。CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y に変えると 124 MB/s まで伸びました (+49%)。

ただし cache line が大きくなる分、ランダムアクセス時の miss 1 回あたりに転送されるバイト数が増えるため、参照されない領域も含めて MSPI を引いてしまうケースが増えます。シーケンシャル read 中心のワークロードなら 64 B が有利、まばらに散ったランダム read が支配的なら 32 B のほうが MSPI の無駄が少なくなる可能性があります。ワークロードの性格に合わせて選ぶのが妥当そうです。

実験 2: esp_async_memcpy の罠

PSRAM → 内蔵 SRAM の M2M 転送を計測:

転送サイズ esp_async_memcpy 所要時間 [us] raw GDMA 所要時間 [us]
64 B 12,500 4
1 KB 12,500 4
256 KB ~15,000 3,280

転送サイズに依らず ~12 ms の固定オーバヘッド。原因は esp_async_memcpy が転送ごとに以下を実行しているため:

  1. heap_caps_aligned_calloc() で descriptor 動的確保
  2. esp_cache_msync() で cache flush / invalidate
  3. ISR でコールバック発火、heap 解放

256 KB を 1 発で運ぶ用途なら ~17 MB/s で「使えなくもない」程度。「たまに大きな塊を運ぶ」用途専用と考えるのが安全。

実験 3: Raw GDMA を直接叩く

gdma_* API で descriptor を事前確保・再利用する。ポイント:

  • gdma_transfer_ability_t.psram_trans_align = 64 で cache line と揃える (MSPI burst が割れず効率最大)
  • DMA は完了時に owner=0 を書き戻すので、CPU 側で owner=1 への再武装が必要
  • 起動は gdma_start(rx)gdma_start(tx) → EOF 割り込み待ち、で submit overhead 4 us

Raw GDMA 帯域 (PSRAM → internal RAM)

転送サイズ DMA 帯域 [MB/s] CPU memcpy 帯域 [MB/s]
1 KB 49.2 357
16 KB 76.9 370
64 KB 79.2 126
256 KB 79.8 126
  • DMA は plateau が ~80 MB/s 付近 (MSPI 124 MB/s の 64% 程度)
  • CPU memcpy は cache hit するサイズだと 5 倍程度速いケースもあった
  • このベンチの範囲では DMA が CPU memcpy を上回る場面は見られず、価値は速度より「CPU と並列に動ける」点に出やすそうです

実験 4: CPU vs DMA の MSPI bus 競合

PRO_CPU で seq read、APP_CPU で DMA flooder を並走:

シナリオ CPU 帯域 [MB/s] DMA 帯域 [MB/s] 合計 [MB/s]
CPUのみ 124.8 0 124.8
DMAのみ 1ch 0 79.7 79.7
CPU + DMA 1ch (並走) 67.4 65.8 133.2

単独時で正規化すると CPU は 54%、DMA は 83% 残る計算で、MSPI アービタは DMA 寄りに優先する挙動と読めます。

→ DMA を走らせている間、CPU 側の PSRAM cache miss は latency が増える傾向。LCD DMA を回しながら framebuffer を CPU で書き換える構成などで影響が出やすそうです。

実験 5: 2ch DMA を同時に走らせる

シナリオ DMA 帯域 [MB/s] 合計 [MB/s]
DMAのみ 1ch 79.4
DMAのみ 2ch 94.6 (+19%)
CPU + DMA 2ch (並走) 66.0 133.3

合計帯域という観点では、2ch にしても +19% で 2 倍にはならず、CPU 並走時の合計も 1ch / 2ch ともに 133 MB/s 付近に収束しました (本ベンチ範囲)。MSPI が共有資源である以上、帯域だけを目的に 2ch にしても伸びは限定的、という見え方です。

ただし 2ch DMA にはそれぞれを独立に制御できるメリットがあります。例えば「LCD への streaming 用」と「センサバッファの取り込み用」を別々のタイミング・サイズで並走させたい、といった用途では 2ch 構成自体に価値があります。帯域目的か、独立制御目的かで採否が分かれそうです。

実験 6: Cache precharge (参考値)

cache を先に温めておく precharge は、precharge 中に他の処理を走らせて時間を隠蔽できれば効果が見込める手法。今回の測定は precharge 直後に同じデータを直列で read する構成で、隠蔽対象の処理を挟んでいないため、precharge そのもののコストがそのまま時間に乗る形になっています。参考値として載せておきます (隠蔽できる構成や working set が cache に収まる前提なら結果の見え方は変わりそう):

戦略 (全て同一コア):

  1. cold: invalidate してから読む
  2. touch: invalidate → CPU で 64 B stride で touch read → 本番 read
  3. preload: invalidate → ROM の Cache_Start_DCache_Preload → 本番 read
サイズ cold のみ [us] touch + warm read [us] 備考
16 KB (cache 内) 132 194 warm read は 237 MB/s で cache hit している
64 KB (cache 外) 516 1030 working set が cache を超え precharge 中に evict
  • HW preload (Cache_Start_DCache_Preload) も CPU touch とほぼ同等の所要時間。
  • 直列実行の参考値であり、precharge が有効な構成 (PSRAM を触らない計算と並走、別コアでの touch、非同期 preload と本処理のオーバーラップなど) では別の結果になり得ます。

まとめ

経路別の実測帯域

経路 実測 [MB/s]
L1 D-cache hit (PSRAM, ≤32 KB) 239
PSRAM cache miss seq 124.8
PSRAM random read 8.2
1ch GDMA PSRAM→DRAM 79.8
MSPI 実用上限 ~133
Internal DRAM ~1000

設計ルール

  1. esp_async_memcpy は小転送に使わない (12 ms 固定オーバヘッド)
  2. Cache line サイズはワークロード次第。seq read 中心なら 64 B (32 B 比 +49%)、ランダムが多いなら miss あたりの転送量が小さい 32 B も検討
  3. DMA は MSPI 上で CPU より優先される挙動。並走時 CPU は半分程度に落ちる傾向 (本ベンチ観測)
  4. 2ch DMA は帯域目的だとスケールが鈍い (本ベンチ +19%)。一方で 2ch を独立に制御したい用途では別の価値あり
  5. Cache precharge は隠蔽前提の手法。precharge 時間を別タスクで隠せる構成でないと、直列で測ると単に 1 pass 分余計に見える
  6. 重い streaming は内蔵 DRAM (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) に置く

補足: メモリマップ

領域 アドレス 実体 access path レイテンシ
internal IRAM 0x4037_0000 内蔵 SRAM (命令属性) 直接 数 ns (~1 GB/s)
internal DRAM 0x3FC8_0000 内蔵 SRAM (データ属性) 直接 数 ns (~1 GB/s)
PSRAM 0x3C00_0000 外部 Octal SPI RAM L1 D-cache 経由 hit: ns オーダ / miss: hundreds of ns オーダ
Flash XIP 0x4200_0000 外部 SPI Flash L1 I-cache 経由 hit: ns オーダ / miss: us オーダ
  • IRAM と DRAM は同じ物理 SRAM の別ビュー
  • 内蔵 SRAM は CPU と DMA が同じ物理メモリを直接見るので msync 不要
  • L1 D-cache は 両コア共有 32 KB (per-core ではない)

参考

一部AIで生成しています。チェックはしていますが悪しからず...

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?