NVTX
NVTX for CとC++
このREADMEは、C/C++に特化したNVTXのトピックをカバーしています。一般的なNVTXの情報については、NVTXリポジトリのルートにあるREADMEをご覧ください。
NVTX APIはC言語で書かれており、NVTX C++ APIはC APIの一部をラップする形で実装されています。C++では、NVTX C APIとNVTX C++ APIの両方を使用できます。
NVTX APIリファレンスガイド
- NVTX C APIリファレンス
- NVTX C++ APIリファレンス
NVTXのCおよびC++ヘッダーファイルには、Doxygenコメントが含まれており、これらのコメントからリファレンスドキュメントが生成されています。
NVTX C/C++の例
Nsight Systemsを用いたシンプルなNVTX C++例
このC++の例では、関数some_function
に対して、その名前を使用してPush/Pop範囲のアノテーションを行っています。この範囲は関数の冒頭で始まり、関数がリターンする際に自動的に終了します。この関数はループを実行し、各反復で1秒間スリープします。ローカル変数nvtx3::scoped_range
は、ループ本体のスコープをPush/Pop範囲でアノテーションします。ループの反復範囲は、関数範囲内にネストされています。
#include <nvtx3/nvtx3.hpp>
void some_function()
{
NVTX3_FUNC_RANGE(); // 関数全体をカバーする範囲
for (int i = 0; i < 6; ++i) {
nvtx3::scoped_range loop{"loop range"}; // 各反復の範囲
// 各反復を1秒間持続させる
std::this_thread::sleep_for(std::chrono::seconds{1});
}
}
通常、このプログラムは6秒間待機し、他には何もしません。
NVIDIA Nsight Systemsからこれを起動すると、タイムライン上でこの実行を見ることができます:
NVTXの行には、最上位の範囲に関数の名前「some_function」と、ネストされた範囲に「loop range」というメッセージが表示されます。ループの各反復は、予想通り1秒ずつ続きます。
NVTX C APIを使用すると、以下の例で同じタイムラインが得られます:
#include <nvtx3/nvToolsExt.h>
void some_function()
{
nvtxRangePush(__func__); // 関数全体をカバーする範囲
for (int i = 0; i < 6; ++i) {
nvtxRangePush("loop range"); // 各反復の範囲
// 各反復を1秒間持続させる
std::this_thread::sleep_for(std::chrono::seconds{1});
nvtxRangePop(); // 内側の範囲を終了
}
nvtxRangePop(); // 外側の範囲を終了
}
関数がnvtxRangePop
呼び出しの前にリターンやthrowに到達すると、範囲は未完了のままとなり、ツールの動作は未定義です。C++ APIを使用すると、ローカル変数scoped_range
がデストラクタ内でnvtxRangePop
を呼び出すため、より安全です。
マーカー
C言語:
nvtxMark("This is a marker");
C++:
nvtx3::mark("This is a marker");
Push/Pop範囲
C言語:
nvtxRangePush("This is a push/pop range");
// この範囲で興味深い操作を行う
nvtxRangePop(); // Popは対応するPushと同じスレッドで行う必要があります
C++:
{
nvtx3::scoped_range range("This is a push/pop range");
// この範囲で興味深い操作を行う
// scoped_rangeオブジェクトがスコープから外れると範囲がpopされます
}
Start/End範囲
C言語:
// コードのどこかで:
nvtxRangeHandle_t handle = nvtxRangeStart("This is a start/end range");
// Start呼び出しとは別のスレッドであっても良い
nvtxRangeEnd(handle);
C++:
// オブジェクトのライフタイムの周囲に範囲を自動的に開始・終了する:
class SomeResource // 移動可能だがコピー不可能
{
// クラスのメンバー、メソッドなど
// コンストラクションで範囲が開始され、デストラクションで終了
nvtx3::unique_range range(objectInstanceName);
};
リソースの命名
NVTX C APIはすべてのリソース命名に使用されます。
// 現在のCPUスレッドに名前を付ける
nvtxNameOsThread(pthread_self(), "Network I/O");
// CUDAストリームに名前を付ける
cudaStream_t graphicsStream, aiStream;
cudaStreamCreate(&graphicsStream);
cudaStreamCreate(&aiStream);
nvtxNameCudaStreamA(graphicsStream, "Graphics");
nvtxNameCudaStreamA(aiStream, "AI");
自分のコードでNVTXを使用する方法は?
CおよびC++向けのNVTXは、ヘッダーファイルのみのライブラリで、依存関係はありません。使用したいヘッダーを#include
し、NVTX関数を呼び出すだけです! NVTXは、最初のNVTX関数呼び出し時に自動的に初期化されます。
バイナリライブラリにリンクする必要はありません。POSIXプラットフォームでは、リンカコマンドラインに-ldl
オプションを追加する必要があります。
注: 古いバージョンのNVTXでは、動的ライブラリへのリンクが必要でした。NVTXバージョン3は同じAPIを提供しますが、ライブラリにリンクする必要がなくなりました。#include
にnvtx3
ディレクトリをプレフィックスとして使用して、NVTX v3をインクルードしていることを確認してください:
C言語:
#include <nvtx3/nvToolsExt.h>
C++:
#include <nvtx3/nvtx3.hpp>
CおよびC++ APIはヘッダーファイルのみで構成されており、依存関係もなく、明示的な初期化も不要なため、他のヘッダーファイルのみのライブラリの注釈に適しています。同じ翻訳単位または異なる翻訳単位で異なるバージョンのNVTXヘッダーを使用しているライブラリでも、ベストプラクティスに従っていれば、競合は発生しません。
CMakeでNVTXを使用する
CMakeを使用するプロジェクトの場合、同梱のCMakeLists.txtは、必要なインクルードパスを設定し、-ldl
リンカーオプションを設定するnvtx3-c
およびnvtx3-cpp
ターゲットを提供します。
NVTXのローカルコピーを使用する
たとえば、プロジェクトのレイアウトが次のようになっているとします:
CMakeLists.txt
imports/
CMakeLists.txt
他のサードパーティライブラリ...
NVTX/ (このディレクトリのGitHubからのコピー)
CMakeLists.txt
include/
nvtx3/
(すべてのNVTX v3ヘッダー)
source/
CMakeLists.txt
main.cpp
ルートのCMakeLists.txtファイルには以下が含まれています:
add_subdirectory(imports)
add_subdirectory(source)
imports/CMakeLists.txt
ファイルには以下が含まれています:
add_subdirectory(NVTX)
add_subdirectory(...) # 他のインポートされたライブラリ
source/CMakeLists.txt
ファイルでは、NVTXで定義されたCMakeターゲットを使用できます:
add_executable(my_program main.cpp)
target_link_libraries(my_program PRIVATE nvtx3-cpp)
CMakeパッケージマネージャー(CPM)を使用する
CMakeパッケージマネージャー(CPM)は、CMakeがプロジェクトで初めて実行される際に依存関係を自動的にダウンロードするユーティリティです。NVTX v3はヘッダーのみなので、ダウンロードは高速です。ダウンロードしたファイルは、外部キャッシュディレクトリに保存して、クリーンビルド時の再ダウンロードを避け、オフラインビルドを可能にします。まず、CPMのリポジトリからCPM.cmakeをダウンロードし、プロジェクトに保存します。次に、CMakeコードで以下のようにしてNVTXを直接GitHubから取得できます(CMake 3.14以上が必要です):
include(path/to/CPM.cmake)
CPMAddPackage(
NAME NVTX
GITHUB_REPOSITORY NVIDIA/NVTX
GIT_TAG release-v3
SOURCE_SUBDIR c
)
add_executable(some_c_program main.c)
target_link_libraries(some_c_program PRIVATE nvtx3-c)
add_executable(some_cpp_program main.cpp)
target_link_libraries(some_cpp_program PRIVATE nvtx3-cpp)
C/C++のバージョンとコンパイラ
C言語
NVTX C APIは、標準のC89を使用して実装されたヘッダーファイルのみのライブラリです。多くの一般的なコンパイラで-std=gnu90
以降のオプションを使用してコンパイルできます。テスト済みのコンパイラには以下が含まれます:
- GNU gcc
- clang
- Microsoft Visual C++
- NVIDIA nvcc
これらのコンパイラにおけるC89のサポートは、何年も変わっていないため、非常に古いコンパイラバージョンでも動作するはずです。
C++
NVTX C++ APIは、NVTX C APIのラッパーとして実装されたヘッダーファイルのみのライブラリで、標準のC++11を使用しています。C++ヘッダーはCヘッダーと共に提供されます。NVTX C++は、-std=c++11
以降のオプションを使用して多くの一般的なコンパイラでコンパイルできます。テスト済みのコンパイラには以下が含まれます:
- GNU g++ (4.8.5から11.1まで)
- clang (3.5.2から12.0まで)
- Microsoft Visual C++ (VS 2015からVS 2022まで)
- VS 2017.7以降では、NVTXはより良いエラーメッセージ出力を有効にします
- NVIDIA nvcc (CUDA 7.0以降)