Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
DirectMLX — это вспомогательная заголовочная библиотека C++ для DirectML, предназначенная для упрощения объединения отдельных операторов в графы.
DirectMLX предоставляет удобные оболочки для всех типов операторов DirectML (DML), а также интуитивно понятные перегрузки операторов, что упрощает создание экземпляров операторов DML и объединение их в сложные графы.
Где найти DirectMLX.h
DirectMLX.h распространяется как программное обеспечение с открытым исходным кодом под лицензией MIT. Последнюю версию можно найти на GitHub DirectML.
Требования к версии
Для 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
Вот еще один пример, который создает граф 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, вызывает ошибки, приводящие к вызову to std::abort , а не к созданию исключения. Это определяется по умолчанию, если исключения недоступны (например, если исключения были отключены в параметрах компилятора). |
| DMLX_USE_WIL | Если #define, исключения генерируются с использованием типов исключений из библиотеки реализации Windows . В противном случае вместо этого используются стандартные типы исключений (например, std::runtime_error). Этот параметр не действует , если определен DMLX_NO_EXCEPTIONS . |
| DMLX_USE_ABSEIL | Если #define, использует Abseil в качестве замены стандартных типов библиотек, недоступных в C++11. К таким типам относятся absl::optional (вместо std::optional), absl::Span (вместо std::span), и absl::InlinedVector. |
| DMLX_USE_GSL | Определяет, следует ли использовать GSL в качестве замены .std::span Если #define, использование of std::span заменяется gsl::span компиляторами on без нативных std::span реализаций. В противном случае вместо этого предоставляется встроенная реализация drop-in. Обратите внимание, что этот параметр используется только при компиляции на компиляторе до C++20 без поддержки std::span, и когда не используется другая замена стандартной библиотеки (например, Abseil). |
Управление тензорной раскладкой
Для большинства операторов DirectMLX вычисляет свойства выходных тензоров оператора от вашего имени. Например, при выполнении операции по dml::Reduce поперечным осям { 0, 2, 3 } с входным тензором размеров { 3, 4, 5, 6 }, DirectMLX автоматически вычислит свойства выходного тензора, включая правильную форму { 1, 4, 1, 1 }.
Однако к другим свойствам выходного тензора относятся Strides, TotalTensorSizeInBytes и GuaranteedBaseOffsetAlignment. По умолчанию DirectMLX задает эти свойства таким образом, чтобы тензор не имел распутья, не имел гарантированного выравнивания смещения основания и имел общий размер тензора в байтах, вычисленный с помощью DMLCalcBufferTensorSize.
DirectMLX поддерживает возможность настройки этих выходных тензорных свойств с помощью объектов, известных как тензорные политики. TensorPolicy — это настраиваемый обратный вызов, который вызывается DirectMLX и возвращает выходные свойства тензора с учетом вычисленного типа данных, флагов и размеров тензора.
Тензорные политики могут быть установлены для объекта dml::Graph и будут использоваться для всех последующих операторов на этом графе. Политики тензора также могут быть заданы непосредственно при создании 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(/* ... */);