DirectMLX は DirectML 用の C++ ヘッダー専用ヘルパー ライブラリであり、個々の演算子をグラフに簡単に作成することを目的としています。
DirectMLX は、すべての DirectML (DML) 演算子の種類に対応する便利なラッパーと、直感的な演算子オーバーロードを提供するため、DML 演算子のインスタンス化と複雑なグラフへのチェーンが簡単になります。
見つける場所 DirectMLX.h
DirectMLX.h は、MITライセンスの下でオープンソースソフトウェアとして配布されています。 最新バージョンは、 DirectML GitHub にあります。
バージョンの要件
DirectMLX には、DirectML バージョン 1.4.0 以降が必要です ( 「DirectML のバージョン履歴」を参照)。 以前のバージョンの DirectML はサポートされていません。
DirectMLX.h には、次のような C++11 対応コンパイラが必要です (ただし、これらに限定されません)。
- Visual Studio 2017
- Visual Studio 2019
- クラン10
C++17 (またはそれ以降) のコンパイラが推奨されるオプションであることに注意してください。 C++11 のコンパイルは可能ですが、不足している標準ライブラリ機能を置き換えるために、サードパーティのライブラリ ( GSL や Abseil など) を使用する必要があります。
DirectMLX.hのコンパイルに失敗する設定がある場合は、GitHubで問題を報告してください。
基本的な使用方法
#include <DirectML.h>
#include <DirectMLX.h>
IDMLDevice* device;
/* ... */
dml::Graph graph(device);
// Input tensor of type FLOAT32 and sizes { 1, 2, 3, 4 }
auto x = dml::InputTensor(graph, 0, dml::TensorDesc(DML_TENSOR_DATA_TYPE_FLOAT32, {1, 2, 3, 4}));
// Create an operator to compute the square root of x
auto y = dml::Sqrt(x);
// Compile a DirectML operator from the graph. When executed, this compiled operator will compute
// the square root of its input.
DML_EXECUTION_FLAGS flags = DML_EXECUTION_FLAG_NONE;
ComPtr<IDMLCompiledOperator> op = graph.Compile(flags, { y });
// Now initialize and dispatch the DML operator as usual
次に、 2 次数式を計算できる DirectML グラフを作成する別の例を示します。
#include <DirectML.h>
#include <DirectMLX.h>
IDMLDevice* device;
/* ... */
std::pair<dml::Expression, dml::Expression>
QuadraticFormula(dml::Expression a, dml::Expression b, dml::Expression c)
{
// Quadratic formula: given an equation of the form ax^2 + bx + c = 0, x can be found by:
// x = -b +/- sqrt(b^2 - 4ac) / (2a)
// https://en.wikipedia.org/wiki/Quadratic_formula
// Note: DirectMLX provides operator overloads for common mathematical expressions. So for
// example a*c is equivalent to dml::Multiply(a, c).
auto x1 = -b + dml::Sqrt(b*b - 4*a*c) / (2*a);
auto x2 = -b - dml::Sqrt(b*b - 4*a*c) / (2*a);
return { x1, x2 };
}
/* ... */
dml::Graph graph(device);
dml::TensorDimensions inputSizes = {1, 2, 3, 4};
auto a = dml::InputTensor(graph, 0, dml::TensorDesc(DML_TENSOR_DATA_TYPE_FLOAT32, inputSizes));
auto b = dml::InputTensor(graph, 1, dml::TensorDesc(DML_TENSOR_DATA_TYPE_FLOAT32, inputSizes));
auto c = dml::InputTensor(graph, 2, dml::TensorDesc(DML_TENSOR_DATA_TYPE_FLOAT32, inputSizes));
auto [x1, x2] = QuadraticFormula(a, b, c);
// When executed with input tensors a, b, and c, this compiled operator computes the two outputs
// of the quadratic formula, and returns them as two output tensors x1 and x2
DML_EXECUTION_FLAGS flags = DML_EXECUTION_FLAG_NONE;
ComPtr<IDMLCompiledOperator> op = graph.Compile(flags, { x1, x2 });
// Now initialize and dispatch the DML operator as usual
その他の例
DirectMLX を使用した完全なサンプルは、 DirectML GitHub リポジトリにあります。
コンパイル時オプション
DirectMLX では、ヘッダーのさまざまな部分をカスタマイズするためのコンパイル時 #define がサポートされています。
| 選択肢 | 説明 |
|---|---|
| DMLX_NO_EXCEPTIONS | #define すると、エラーが発生し、例外がスローされるのではなく、 std::abort が呼び出されます。 これは、例外が使用できない場合 (たとえば、コンパイラ オプションで例外が無効になっている場合) に既定で定義されます。 |
| DMLX_USE_WIL | #define した場合、 例外は Windows 実装ライブラリ の例外の種類を使用してスローされます。 それ以外の場合は、代わりに標準の例外タイプ ( std::runtime_error など) が使用されます。
DMLX_NO_EXCEPTIONSが定義されている場合、このオプションは無効です。 |
| DMLX_USE_ABSEIL | もし #define なら、C++11 で利用できない標準ライブラリ型のドロップイン置換として Abseil を使用します。 これらのタイプには、 absl::optional ( std::optional の代わりに)、 absl::Span ( std::span の代わりに)、 absl::InlinedVector が含まれます。 |
| DMLX_USE_GSL |
std::span の代わりに GSL を使用するかどうかを制御します。 #define した場合、std::spanの使用は、ネイティブstd::span実装のないコンパイラでのgsl::spanに置き換えられます。 それ以外の場合は、代わりにインライン ドロップイン実装が提供されます。 このオプションは、 std::spanをサポートしていない C++20 より前のコンパイラでコンパイルする場合、および他のドロップイン標準ライブラリの代替品 (Abseil など) が使用されていない場合にのみ使用されることに注意してください。 |
テンソルレイアウトの制御
ほとんどの演算子では、DirectMLX はユーザーに代わって演算子の出力テンソルのプロパティを計算します。 たとえば、サイズ { 3, 4, 5, 6 } の入力テンソルを使用して軸{ 0, 2, 3 }間でdml::Reduceを実行する場合、DirectMLX は{ 1, 4, 1, 1 }の正しい形状を含む出力テンソルのプロパティを自動的に計算します。
ただし、出力テンソルの他のプロパティには、 Strides、 TotalTensorSizeInBytes、 GuaranteedBaseOffsetAlignment などがあります。 既定では、DirectMLX は、テンソルにストライディング、保証されたベース オフセット アライメント、 および DMLCalcBufferTensorSize によって計算された合計テンソル サイズ (バイト単位) を持つように、これらのプロパティを設定します。
DirectMLX では、 テンソル ポリシーと呼ばれるオブジェクトを使用して、これらの出力テンソル プロパティをカスタマイズする機能がサポートされています。 TensorPolicy は、DirectMLX によって呼び出されるカスタマイズ可能なコールバックであり、テンソルの計算データ型、フラグ、およびサイズを指定して出力テンソル プロパティを返します。
テンソル ポリシーは dml::Graph オブジェクトで設定でき、そのグラフ上の後続のすべての演算子に使用されます。 Tensor ポリシーは、 TensorDesc を構築するときに直接設定することもできます。
したがって、DirectMLX によって生成されるテンソルのレイアウトは、テンソルに適切なストライドを設定する TensorPolicy を設定することで制御できます。
例 1
// Define a policy, which is a function that returns a TensorProperties given a data type,
// flags, and sizes.
dml::TensorProperties MyCustomPolicy(
DML_TENSOR_DATA_TYPE dataType,
DML_TENSOR_FLAGS flags,
Span<const uint32_t> sizes)
{
// Compute your custom strides, total tensor size in bytes, and guaranteed base
// offset alignment
dml::TensorProperties props;
props.strides = /* ... */;
props.totalTensorSizeInBytes = /* ... */;
props.guaranteedBaseOffsetAlignment = /* ... */;
return props;
};
// Set the policy on the dml::Graph
dml::Graph graph(/* ... */);
graph.SetTensorPolicy(dml::TensorPolicy(&MyCustomPolicy));
例 2
DirectMLX には、いくつかの代替テンソル ポリシーも組み込まれています。 たとえば、 InterleavedChannel ポリシーは便宜上提供されており、NHWC 順序で記述されるようなストライドを持つテンソルを生成するために使用できます。
// Set the InterleavedChannel policy on the dml::Graph
dml::Graph graph(/* ... */);
graph.SetTensorPolicy(dml::TensorPolicy::InterleavedChannel());
// When executed, the tensor `result` will be in NHWC layout (rather than the default NCHW)
auto result = dml::Convolution(/* ... */);