SSD HOWTO：SLCキャッシュを上手く使う(2/4)

# はじめに
　NANDフラッシュメモリを不揮発性記憶媒体として使用するSolid State Drive（以降SSDと記載）が備える機能のひとつとして「SLCキャッシュ」を取り上げ、SLCキャッシュを上手く使うためのノウハウをまとめています。

　[前回](https://qiita.com/ken-yossy/items/2dcbc41acbbf78d0af9e)は容量の視点からSLCキャッシュの制御方式を説明し、上手く使用する方法をまとめました。

　今回は「SLCキャッシュに記録されるデータ」の視点でまとめます。

# まとめ

* データサイズの小さいライトコマンドをSLCキャッシュに書く制御方式がある
* 空間的もしくは時間的局所性を持つデータはSLCキャッシュに書き込まれやすい
* ライトするデータに属性を付与する仕組みもあるが現状のOSはほとんど非対応で使えない

# 【再掲】SLCキャッシュの制御方式

　代表的な「SLCキャッシュの制御方式」を再掲します。

　SLCキャッシュの挙動を特徴づける項目には大きく4つあります。それは、容量、データ、追い出し処理の契機、そして追い出しアルゴリズム、です。

:::note warn
この記事では代表的なものを示します。ここに示した項目や方式以外にも、各メーカーおよび製品に特有の項目の存在や方式の実装が考えられます。その場合、SLCキャッシュの特性も変化します。
:::

_表：SLCキャッシュの動作を特徴づける項目と代表的な制御方式_
| 項目| 代表的な方式 | 概要 |
|-:|:-|:-|
| 容量  | 静的 | 静的に容量を確保して運用  |
|   | 動的  | データ量に応じて容量を増減  |
| 記録データ  | 何でも  | 区別なし  |
|   | 小サイズのみ  | 一定サイズ未満  |
|   | 特定データのみ | 何らかの法則で決定 |
| 追い出し契機 | 容量 | （残）容量のみで判断 |
|                   | アイドル時 | アイドル時に積極的に実施 |
| 追い出しアルゴリズム | Least Recently Used (LRU) | アクセス頻度が少ない順 |
|                     | First-In-First-Out (FIFO) | 記録された時刻が古い順 |

　この表に記載した項目のうち今回は「記録データ」に注目します。

# 「記録するデータ」での制御とは

　記録するデータによる制御とは、ここでは「ホストから受領したライトコマンドの書き込みデータをSLCキャッシュに記録するかどうかの制御」を指すこととします。例えば「このライトコマンドはデータサイズが小さいからSLCキャッシュに書こう」のような制御です。

　SSDが対応するインターフェース（SATAやNVMeなど）において、ホストから受領するライトコマンドに付随する代表的な情報は以下のものです。

* ライトするデータのアドレス(LBA)
* ライトするデータのサイズ（セクタ数）
* 不揮発メディアにデータを書いた時点でコマンド完了とするか
* ライトするデータの属性

　このうち、3つめの「不揮発メディアにデータを書いた時点でコマンド完了とするか」という情報のみ他のものとは種類が異なります。このためSSDの内部処理に与える影響も異なります。今回はSLCキャッシュの制御に焦点をあてますのでこの情報は取り扱いません。

　また厳密に言えば、SSD内部でのデータコピー処理時にコピー対象のデータをSLCキャッシュに記録しても構わないのですが、それについてもここでは扱いません。

# 具体的な制御方法と「上手く使う」方法

　それでは各情報を使用したSLCキャッシュの制御方法と、各制御方法に対する「SLCキャッシュを上手く使う」方法の例を示します。

## なんでもSLCキャッシュに書き込む

　この制御方式は、データサイズに代表されるライトコマンドの付随情報に依存せず受領したデータをSLCキャッシュに書き込む方式です。SSDの内部処理がシンプルになり結果として他の制御方式よりもデータアクセス性能が高くなる可能性もあります。

　この制御方式を採用したSLCキャッシュに対しては書き込むデータの属性を工夫しても効果がありませんので、SLCキャッシュを上手く使うには他の項目に注目する必要があります。例えば、前回の記事で説明した「SLCキャッシュの容量に注意する」などです。

## 小サイズのデータのみSLCキャッシュに書き込む

　この制御方式は、「データサイズが小さいライトコマンドのデータのみ（もしくは優先して）SLCキャッシュに書き込む」というものです。

　この方式の目的のひとつはSLCキャッシュの容量の有効活用です。前回説明した通りSLCキャッシュの容量には限りがあります。そしてSLCキャッシュの容量を「空ける」にはSLCキャッシュに記録されているデータをTLCなどの多値記憶に追い出す処理が必要になり、この追い出し処理が発生するとホストから見たSSDのデータアクセス性能が低下する要因になります。

　このため、SLCキャッシュの容量が満杯もしくは追い出しを必要とする容量になるまでにできるだけ多くのライトコマンドをSLCキャッシュで受けるには書き込むサイズの小さいライトコマンドを対象としたほうが良い、となります。

　NANDフラッシュメモリのデータ読み書きはページ単位であり、特にTLCなどの多値記憶でデータを読み書きする場合はできるだけ多くのNANDフラッシュメモリチップに対して同時並列に読み書きすることで性能を高めます。例えば、ページサイズが16 KBでプレーン数が4のTLC NANDフラッシュメモリチップを8チップ搭載するSSDでは、TLCでの書き込み時は16 KB x 4プレーン x 8チップ = 512 KBのデータを全チップに振り分けて一度に書き込むことが望ましいです。

　このことから、例えば1つのライトコマンドで1 MB以上のデータが書き込まれた場合はSLCキャッシュではなく多値記憶に書き込み、1 MB未満のデータはSLCキャッシュに一旦書き込んでおいてあとで他のデータと合わせて1 MB以上にまとめて多値記憶に書き込む、などの制御方法が考えられます。

　イメージとしては、図1のようにSLCキャッシュを「バッファ」として使用するものです。
 
![SLCキャッシュをバッファとして使用するイメージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/792f3b69-4917-4198-8a09-1aeae8cc7786.png "SLCキャッシュをバッファとして使用するイメージ")
_図1：SLCキャッシュをバッファとして使用するイメージ（図中のサイズはあくまでも例）_

　これが「データサイズが小さいライトコマンドのデータのみSLCキャッシュに書き込む」という制御です。

　この制御方式を採用したSLCキャッシュを上手く使うには、SLCキャッシュに書き込みたいデータはなるべく小分けにしてライトコマンドを発行する必要があります。
 
　「SSDにどのようなライトコマンドを発行するか」ということは通常OS（ファイルシステムやデバイスドライバ）の管理下にありユーザによる指定は難しいことが多いですが、例えば以下のような用途にはこの制御方式のSLCキャッシュを搭載したSSDが適していると考えられます。
 
* サイズの小さいファイルの記録
* 毎回更新量が少ないファイルの記録

## データの書き込み先LBAに注目する

　この制御方法は、ライトコマンドの「書き込むデータのアドレス(LBA)」に注目する方法です。例えば以下のようなものです。

1. SLCキャッシュ内に記録されているもしくは以前SLCキャッシュに記録されていたデータに近いアドレスのデータをSLCキャッシュに記録する
1. 特定のLBA領域のデータをSLCキャッシュに記録する

　前者は「データの空間的、時間的局所性を利用する」というまさに「キャッシュ」の基本的な制御方法であり、その効果はコンピューティングの歴史が証明しています。

　この制御方式を採用しているSSDを使う場合、まず空間的局所性の視点では、SLCキャッシュに書き込みたいデータのアドレスをなるべく狭くすることでSLCキャッシュの効果を得やすくなります。
 
　アドレス(LBA)割り当てはOSやファイルシステムが行いユーザによる直接指定は難しいので、ユーザとしては読み書きするデータ（ファイル）の総容量ができるだけSLCキャッシュ容量より小さくなるようにすることが上手く活用するコツです。

　また時間的局所性の視点では、書き込んでから時間をあけずに同じファイルを更新するとSLCキャッシュに書き込まれやすくなります。

　通常OSやファイルシステムの管理するバッファ（キャッシュ）が存在しますので、短い間隔での読み書きはこれらのバッファとSLCキャッシュを合わせたシステム全体のキャッシュを上手く活用することに繋がります。

　一方後者については、対象とするLBA領域をSSD自ら学習して抽出する方法やホスト（ユーザ）が設定する方法などがあります。

　Western Digitalのソフトウェア[Dashboard](https://support-jp.wd.com/app/products/downloads/softwaredownloads)で設定できるGaming Mode<sup>[1]</sup>や、Solidigmのソフトウェア[Synergy](https://www.solidigm.com/products/client/synergy.html)で設定できる"Fast Lane"などの機能は、高速にアクセスできることが望ましいデータをSSDが独自に検出し、それらのデータをできるだけSLCキャッシュに載せておく機能に見えます。

　上記のような機能を持つSSDであればそれらの機能を活用することが最適です。ただし、これらの機能はどのデータをSLCキャッシュに配置すべきかをSSDコントローラがヒューリスティックアルゴリズムにより判断することが多く、必ずしも効果を得られない、また設定してから効果を得られるまで時間がかかる、などの現象が観測されることもあり注意が必要です。

## ライトするデータの属性に注目する

　例えばNVMeであればライトコマンドに図2のような属性を付与できます。

![NVMeのWriteコマンドに付与可能な属性](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/ab807547-d5bb-7ac6-3fc8-2162c3f6f166.png "NVMeのWriteコマンドに付与可能な属性")
_図2：NVMeのWriteコマンドに付与可能な属性(NVMe 1.4c)_

　図2に記載された属性のうち、例えばアクセスレイテンシに関する項目(Access Latency)が「低レイテンシ(Low)」と指定されていた場合はSLCキャッシュに書き込むことでこの指定を満足できる可能性が高くなりますし、アクセス頻度に関する項目(Access Frequency)でReadもしくはWriteの頻度が高いと指定されていた場合もSLCキャッシュに書き込むことでSLCキャッシュの効果を得られます。

　データに対して直接属性を指定できることから、SLCキャッシュの容量など他の制約が許す状況であればその効果を得られる可能性が高い機能です。
 
　ただ残念なのは、OSやデバイスドライバが存在する環境ではユーザからこれらの属性を利用することが難しいことと、現状これらの属性を活用しているOSが見られないことです。

　このため、仮にSSDがこの制御方法を実装していても、これらの属性の活用に対応したファイルシステムなどを使わない限りその効果は得られません。

# おわりに

　この記事では、「SLCキャッシュに記録するデータの制御」の視点で見たSLCキャッシュの活用方法をまとめました。

　いくつかの制御方法を説明しましたが、ユーザレベルで対応（設定）可能な項目は少なく、これらの制御方法を上手く利用してSLCキャッシュの効果を得ることはなかなか難しいです。

　逆に、読み書きするデータの総容量をできるだけSLCキャッシュの容量より小さくする、読み書きするデータのサイズを小さくする、などの工夫のほうが重要だと言えます。

　次回は「追い出し契機」に関する制御方式に注目します。

# References
[1] Western Digital, _"[Western Digital Dashboard Gaming Mode 2.0](https://support-en.wd.com/app/answers/detailweb/a_id/34938)"_, Retrieved on Jan. 24, 2024

# ライセンス表記
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="クリエイティブ・コモンズ・ライセンス" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />この記事は<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンス</a>の下に提供されています。