C言語で永続的メモリのプログラミングを教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
本記事は以下の記事を理解していることを前提とします.
目次
永続的メモリとは【不揮発性メモリとの違いを解説】
永続的メモリ(Persistent Memory)とは,データ構造を作成または最後に変更したプロセスの終了後でも,メモリ命令またはメモリAPIを使用してアクセスし続けることができるように,データ構造を効率的に保存する方法または装置のことです.
永続的メモリは,不揮発性メモリ(Non-Volatile Memory)と混同されることが多いですが,永続的メモリを作成したプロセスの障害領域の外に存在するプログラムの状態を重視するという点で,永続性の概念と密接な関係があります.
ここで,不揮発性とは,メモリ技術の特性の一つで,コアメモリ,フラッシュメモリ,MRAM/PCRAM/ReRAM等のメモリ技術は,本質的に不揮発性です.
すなわち,それらが含むデータは電源サイクルの後にも保存され続けるということです.
逆に電源サイクルの後にデータが消えるメモリのことを揮発性メモリ(Volatile Memory)と呼びます.
これに対して,永続的メモリは,コンピュータアーキテクチャの特性の一つです.
つまり,CPUがメモリバス経由で直接アドレス指定できるメインメモリの内容は,電源再投入後も利用可能であるということです.
※永続的メモリの逆は,非永続的メモリ(Impersistent Memory)になります.
永続的メモリと不揮発性メモリの違いをスマートフォン(スマホ)の例で解説します.
スマホには,揮発性メモリ(SRAM/DRAM)と不揮発性メモリ(Flash)の両方が搭載されています.
しかし,コンピュータアーキテクチャの観点からは,Flashはストレージ(I/Oバスによる間接アクセス)として使用され,メモリ(メモリバスによる直接アクセス)としては使用されません.
そのため,スマホを再起動するたびに,ソフトウェアがストレージからデータを読み出し,メモリにコピーして動作させる必要があります.
つまり,不揮発性メモリはあっても,永続的メモリはないわけです.
一方,NVIDMM-Nメモリモジュール(同じ記憶容量の中にDRAMと不揮発性メモリを混載したDIMM)を使用したコンピュータでは,電源が落ちるとハードウェアによってDRAMのすべてのデータが自動で透過的にフラッシュにコピーされ,電源が入ると同様にDRAMにコピーバックされます.
上記の操作をソフトウエアは明示的に行っていないことに注意して下さい.
つまり,電源投入後,メモリの内容は「最初から存在したかのように」振る舞います.
この場合,多くの時間で揮発性メモリを使用していることになりますが,コンピュータシステムのアーキテクチャの観点からは,メモリは永続的です.
永続的メモリと不揮発性メモリの解説動画はこちらです.
永続的メモリのプログラミングの動機として,I/Oのボトルネックが挙げられます.
例えば,スマホアプリからのI/Oは少ないバイト数になりますが,SQLを介してデータベースへのジャーナリングやページ単位(主に4K)のI/Oが発生してしまいます.
また,そのデータをファイルシステムを介してブロック単位のI/Oや,ファイルシステムのジャーナリングが発生してしまいます.
その後に(レジスタ,キャッシュ,メモリ等と比較して)相対的に遅いHDD/SDD等のストレージに書き込まれます.
このI/Oのボトルネックがシステムの性能劣化を引き起こしてしまいます.
そこで,永続的メモリが解決策となります.
永続的メモリの特徴は以下になります.
- 不揮発性
- DRAMのような性能
- 大きな容量(1ソケットあたり3.0TB)
Intel Optane DC Persistent Memory
Intel Optane DC Persistent Memoryは,永続的メモリの代表例です.
Intel Optane DC Persistent Memoryは3D XPointと呼ばれる不揮発性メモリの技術を利用しています.
ただし,2022年8月にIntelは不揮発性メモリのOptaneメモリビジネスの終了を発表していることに注意して下さい.
Intel Optane DC Persistent Memoryに対応するXeonプロセッサ,OSやソフトウェアの書き換えのコストが高いからだと思われます.
Intel Xeon Phiみたいな感じですね...
今後,何かしらのキッカケで不揮発性メモリのビジネスが復興することに期待しつつ,本記事を読み進めましょう!
参考までに,現在は広く利用されている仮想化技術は,1980~1990年代に一度ビジネスが衰退しています.
仮想化技術を知りたいあなたはこちらからどうぞ.
Intel Optane DC Persistent Memoryの解説動画はこちらです.
Intel Optane DC Persistent Memoryには,Memory ModeとAppDirect Modeがあります.
Memory Modeでは,DRAMは最終レベルのキャッシュ(LLC:Last Level Cache)として機能します.
※DRAMをニアメモリ,Persistent Memoryをファーメモリと呼びます.
また,Intel Optane DC Persistent Memoryは大容量メモリのように動作し,持続性は保証できず,Intel Optane DC Persistent Memoryに直接アクセスできません.
これに対して,AppDirect Modeでは,DRAMとIntel Optane DC Persistent Memoryの両方に直接アクセスでき,持続性を保証できます.
AppDirect Modeの使い方は以下の2つです.
- ファイルシステムの方法
- ユーザアプリケーションから直接アクセス
Intel Optane DC Persistent MemoryのAppDirect Mode「ファイルシステム」
Intel Optane DC Persistent MemoryのAppDirect Mode「ファイルシステム」の手法を解説していきます.
従来のファイルシステムは,HDD/SSDに最適化されていて,OptaneメモリはI/Oとアトミック粒度が異なるため,Optaneに適していなません.
そこで,以下のファイルシステムの方法で解決していきます.
- ページキャッシュの削除
- OptaneメモリはDRAM並みの性能を持ち,ページキャッシュはさらにレイテンシを増加するため
- 例:ext4 + XFS DAX, NOVA
- カーネル空間からユーザ空間への移行
ext4 + XFS DAX
ext4 + XFS DAXは,ext4とXFSファイルシステムのダイレクトアクセス(DAX:Direct Access)のサポートのことです.
DAXは,ページキャッシュを経由してコピーされる必要のない,永続的メモリ(Intel Optane DC Persistent Memory等)によってバックアップされたファイルに直接アクセスする手段です.
したがって,DAXは,ストレージデバイスとユーザ空間に直接ストレージデバイスをマッピングするための読み取り/書き込みのための余分なコピーをバイパスしています.
NOVA
NOVAは,ログ構造ファイルシステムで,ジャーナリングファイルシステムより安価な故障回避性を提供し,不揮発性メモリは高速かつ高性能な同時ランダムアクセスをサポートすることができます.
NOVAの特徴は,単一ログ更新のためのログ構造化をしていることです.
write/msync/chmod等でログを更新する前に,ログエントリ(log entry)を不揮発性メモリに厳密にコミットします.
また,ログをまたいだ更新のための軽量ジャーナリング機構を持ちます.
unlink/rename等でメタデータやデータの代わりにログテール(log tail)をジャーナリングします.
NOVAの講演動画はこちらです.
Strata
Strataは,あるストレージメディアの強みを活かし,他のストレージメディアの弱点を補うクロスメディアのファイルシステムです.
これにより,Strataは性能,容量,シンプルな同期型IOモデルを同時に提供し,単一のストレージデバイスに制約されるファイルシステムよりもシンプルな設計を実現しています.
Strataは,ユーザ空間,カーネル空間,ストレージ層の間で,スケーラブルで高性能な永続性の懸念とストレージ層の管理を分離する新しい責任分担(split of responsibilities)によるログ構造化アプローチを利用しています.
SplitFS
SplitFSは,最新のPMファイルシステムと比較してソフトウェアのオーバヘッドを大幅に削減した,永続的メモリ用ファイルシステムです.
SplitFSは,ユーザ空間のライブラリファイルシステムと既存のカーネルにおける永続的メモリのファイルシステムとの間で,新しい責任分担を実現しています.
ユーザ空間ライブラリファイルシステムは,POSIXコールをインターセプトし,基礎となるファイルをメモリマッピングし,CPUのロードとストアを用いて読み込みと上書きを提供することでデータ操作を処理します.
メタデータ操作は,カーネルの永続的メモリのファイルシステム (ext4 DAX) によって処理されます.
SplitFSは,ファイルの追加やアトミックなデータ操作を効率的にサポートするために,リリンク(relink)と呼ばれる新しいプリミティブを導入しています.
SplitFSは3つの一貫性モード(POSIX,sync,strict)を提供し,異なるアプリケーションが互いに干渉することなく選択することができます.
SplitFSの講演動画はこちらです.
さらなるファイルシステムの応用手法
さらなるファイルシステムの応用手法は以下になります.
CrossFSとWineFSの講演動画はこちらです.
Intel Optane DC Persistent MemoryのAppDirect Mode「ユーザアプリケーションから直接アクセス」
Intel Optane DC Persistent MemoryのAppDirect Mode「ユーザアプリケーションから直接アクセス」を紹介します.
永続的メモリのプログラミング
永続的メモリのプログラミングをする上で,CPUは命令順が入れ替わることや,アトミック粒度が異なることを考慮する必要があります.
また,ブロックデバイスのサイズは4KBまたは8KBで,現在のCPUは8Byteのアトミック更新を保証しています.
永続的メモリのプログラミングには,以下のように多くの研究の方向性があります.
- 永続的メモリアロケータ
- データベースのロギング
- 永続的メモリのためのデータ構造
永続的メモリのプログラミングを行う上で必要な永続的命令は以下になります.
- キャッシュラインフラッシュ命令
- clflush:フラッシュし,キャッシュラインを無効化する(暗黙のうちに順序付けする).
- clflushopt:フラッシュし,キャッシュラインを無効化する.
- clwb:キャッシュラインを無効にすることなく,キャッシュラインをフラッシュする.
- 非一時記憶命令
- moventq:キャッシュラインのフラッシュは不要.
- メモリフェンス命令(clflushopt/clwb/moventq命令は順序を保証するためにメモリフェンスが必要)
- mfence:この命令より前のメモリ命令(load/store命令)の完了を保証する.
- sfence:この命令より前のstore命令の完了を保証する.
永続的メモリアロケータは,ユーザプログラムのバグによる永続的メモリリークやメモリ破壊を防止できます.
また,システムクラッシュからの復旧が可能です.
しかし,クラッシュ整合性のオーバヘッドが増えてしまいます.
具体的には,メモリアロケータにおける永続的メモリのレイテンシはDRAMのレイテンシの2~3倍になります.
このことは,永続的メモリアプリケーションの性能にとって重要になります.
永続的メモリを利用したプログラミングのために,C言語で開発されたPersistent Memory Development Kit(PMDK)を利用します.
※C++言語へのバインドもできます.
標準的なデファクトの永続的メモリアロケータとして,PMDKのlibpmemobjがあります.
ポインタ構造体は,PoolID + offset (16Byte)で構成されています.
また,ルートオブジェクトをサポートしているので,永続的メモリのよく知られた静的な場所に格納されます.
libpmemobjは,従来の揮発性メモリアロケータを継承していて,以下の特徴があります.
- バディアロケータ
- AVL木ベースのメモリ情報管理
- インラインメタデータ管理
- スレッド毎のアリーナ管理
データベースのロギング
従来のデータベースロギングは,従来のデータベース管理システムで管理されます.
従来のデータベース管理システムでは,メモリ(DRAM)とブロックデバイスのストレージ(SSD/HDD等)への冗長な書き込み操作が発生します.
まず揮発性メモリ(DRAM)にコピーし,次に永続的な二次記憶装置(SSD/HDD等)にコピーします.
この課題を解決するために,不揮発性メモリによるデーターベースのロギング手法が提案されました.
NVWALは,DRAMをデータベースのバッファ領域として使用しています.
書き込みトラフィックを減らすために,差分ロギングをしています.
また,高価な永続メモリの割り当て回数を削減するためにユーザ空間のヒープマネージャーを採用しています.
NVWALはトランザクションを考慮した永続性のため,トランザクションの特性を利用したメモリバリア数を削減しています.
Failure-Atomic Slotted Pagingは,以下の3つから構成されています.
- スロットヘッダ:レコード数とキーの並び順のためのレコードオフセット配列から構成
- レコード内容領域:レコードの内容(追加のみ可能)
- 空き領域
スロットヘッダがそのレコードのオフセット情報を持っているときのみ,レコードは可視化されます.
失敗のアトミック性(原子性)のために,スロットヘッダはアトミック的に更新されなければなりません.
スロットヘッダのサイズを64Byteとするハードウェアトランザクショナルメモリを使用しています.
また,ロギング方式を採用しています.
インデックス構造
インデックス構造は,システムソフトウェアの重要な構成要素です.
ここで注目すべきは,上記のすべてのシステムソフトウェアで利用されているB+木の不整合問題で,以下の場合に発生します.
- ノードでのシフト演算を行う場合
- B+木で平衡化を行う場合
B+木の不整合問題を解決する手法として,以下が挙げられます.
CDDS B+木の講演動画は以下になります.
まとめ
C言語で永続的メモリのプログラミングを紹介しました.
また,永続的メモリと不揮発性メモリとの違いを解説しました.
永続的メモリのプログラミングは以下の記事が詳しいです.
- Persistent Memory Programming
- Persistent Memory Programming on Conventional Hardware
- An Empirical Guide to the Behavior and Use of Scalable Persistent Memory
- Improved EXT4 + XFS DAX Implementation Appears Ready To Go For Linux 5.8
- NOVA: A Log-structured File System for Hybrid Volatile/Non-volatile Main Memories
- Strata: A Cross Media File System
- SplitFS: Reducing Software Overhead in File Systems for Persistent Memory
- Designing a True Direct-Access File System with DevFS
- CrossFS: A Cross-layered Direct-Access File System
- WineFS: a hugepage-aware file system for persistent memory that ages gracefully
- NVWAL: Exploiting NVRAM in Write-Ahead Logging
- Failure-Atomic Slotted Paging for Persistent Memory
- Consistent and Durable Data Structures for Non-Volatile Byte-Addressable Memory
- FPTree: A Hybrid SCM-DRAM Persistent and Concurrent B-Tree for Storage Class Memory
- Endurable Transient Inconsistency in Byte-Addressable Persistent B+-Tree
永続的メモリのプログラミングの解説動画はこちらです.
永続的メモリのプログラミングで利用されることが多いC言語のライブラリとしてSPDKが挙げられます.
SPDKを知りたいあなたはこちらからどうぞ.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!