DML_GATHER_ND_OPERATOR_DESC structure (directml.h)

Gathers elements from the input tensor, using the indices tensor to remap indices to entire subblocks of the input. This operator performs the following pseudocode, where "..." represents a series of coordinates, with the exact behavior dependent on the input and indices dimension count.

output[...] = input[indices[...]]

Syntax

struct DML_GATHER_ND_OPERATOR_DESC {
  const DML_TENSOR_DESC *InputTensor;
  const DML_TENSOR_DESC *IndicesTensor;
  const DML_TENSOR_DESC *OutputTensor;
  UINT                  InputDimensionCount;
  UINT                  IndicesDimensionCount;
};

Members

InputTensor

Type: const DML_TENSOR_DESC*

The tensor to read from.

IndicesTensor

Type: const DML_TENSOR_DESC*

The tensor containing the indices. The DimensionCount of this tensor must match InputTensor.DimensionCount. The last dimension of the IndicesTensor is actually the number of coordinates per index tuple, and it cannot exceed InputTensor.DimensionCount. For example, an indices tensor of Sizes {1,4,5,2} with IndicesDimensionCount = 3 means a 4x5 array of 2-coordinate tuples that index into InputTensor.

Starting with DML_FEATURE_LEVEL_3_0, this operator supports negative index values when using a signed integral type with this tensor. Negative indices are interpreted as being relative to the end of the respective dimension. For example, an index of -1 refers to the last element along that dimension.

OutputTensor

Type: const DML_TENSOR_DESC*

The tensor to write the results to. The DimensionCount and DataType of this tensor must match InputTensor.DimensionCount. The expected OutputTensor.Sizes are the concatenation of the IndicesTensor.Sizes leading segments and InputTensor.Sizes trailing segment to yield:

indexTupleSize = IndicesTensor.Sizes[IndicesTensor.DimensionCount - 1]
OutputTensor.Sizes = {
    1...,
    IndicesTensor.Sizes[(IndicesTensor.DimensionCount - IndicesDimensionCount) .. (IndicesTensor.DimensionCount - 1)],
    InputTensor.Sizes[(InputTensor.DimensionCount - indexTupleSize) .. InputTensor.DimensionCount]
}

The output dimensions are right-aligned, with leading 1 values prepended if needed to satisfy up to OutputTensor.DimensionCount.

Here's an example.

InputTensor.Sizes = {3,4,5,6,7}
InputDimensionCount = 5
IndicesTensor.Sizes = {1,1, 1,2,3}
IndicesDimensionCount = 3 // can be thought of as a {1,2} array of 3-coordinate tuples

// The {1,2} comes from the indices tensor (ignoring last dimension which is the tuple size),
// and the {6,7} comes from input tensor, ignoring the first 3 dimensions
// since the index tuples are 3 elements (from the indices tensor last dimension).
OutputTensor.Sizes = {1, 1,2,6,7}

InputDimensionCount

Type: UINT

The number of actual input dimensions within the InputTensor after ignoring any irrelevant leading ones, ranging [1, *InputTensor.DimensionCount*]. For example, given InputTensor.Sizes = {1,1,4,6} and InputDimensionCount = 3, the actual meaningful indices are {1,4,6}.

IndicesDimensionCount

Type: UINT

The number of actual index dimensions within the IndicesTensor after ignoring any irrelevant leading ones, ranging [1, IndicesTensor.DimensionCount]. For example, given IndicesTensor.Sizes = {1,1,4,6}, and IndicesDimensionCount = 3, the actual meaningful indices are {1,4,6}.

Examples

Example 1. 1D remapping

InputDimensionCount: 2
IndicesDimensionCount: 2

InputTensor: (Sizes:{2,2}, DataType:FLOAT32)
    [[0,1],[2,3]]

IndicesTensor: (Sizes:{2,1}, DataType:UINT32)
    [[1],[0]]

// output[y, x] = input[indices[y], x]
OutputTensor: (Sizes:{2,2}, DataType:FLOAT32)
    [[2,3],[0,1]]

Example 2. 2D remapping

InputDimensionCount: 3
IndicesDimensionCount: 2

InputTensor: (Sizes:{1, 2,2,2}, DataType:FLOAT32)
    [ [[[0,1],[2,3]],[[4,5],[6,7]]] ]

IndicesTensor: (Sizes:{1,1, 2,2}, DataType:UINT32)
    [[ [[0,1],[1,0]] ]]

// output[y, x] = input[indices[y, 0], indices[y, 1], x]
OutputTensor: (Sizes:{1,1, 2,2}, DataType:FLOAT32)
    [[ [[2,3],[4,5]] ]]

Remarks

A newer version of this operator, DML_OPERATOR_GATHER_ND1, was introduced in DML_FEATURE_LEVEL_3_0.

Availability

This operator was introduced in DML_FEATURE_LEVEL_2_1.

Tensor constraints

  • IndicesTensor, InputTensor, and OutputTensor must have the same DimensionCount.
  • InputTensor and OutputTensor must have the same DataType.

Tensor support

DML_FEATURE_LEVEL_4_1 and above

Tensor Kind Supported dimension counts Supported data types
InputTensor Input 1 to 8 FLOAT64, FLOAT32, FLOAT16, INT64, INT32, INT16, INT8, UINT64, UINT32, UINT16, UINT8
IndicesTensor Input 1 to 8 INT64, INT32, UINT64, UINT32
OutputTensor Output 1 to 8 FLOAT64, FLOAT32, FLOAT16, INT64, INT32, INT16, INT8, UINT64, UINT32, UINT16, UINT8

DML_FEATURE_LEVEL_3_0 and above

Tensor Kind Supported dimension counts Supported data types
InputTensor Input 1 to 8 FLOAT32, FLOAT16, INT32, INT16, INT8, UINT32, UINT16, UINT8
IndicesTensor Input 1 to 8 INT64, INT32, UINT64, UINT32
OutputTensor Output 1 to 8 FLOAT32, FLOAT16, INT32, INT16, INT8, UINT32, UINT16, UINT8

DML_FEATURE_LEVEL_2_1 and above

Tensor Kind Supported dimension counts Supported data types
InputTensor Input 4 FLOAT32, FLOAT16, INT32, INT16, INT8, UINT32, UINT16, UINT8
IndicesTensor Input 4 UINT32
OutputTensor Output 4 FLOAT32, FLOAT16, INT32, INT16, INT8, UINT32, UINT16, UINT8

Requirements

Requirement Value
Minimum supported client Windows 10 Build 20348
Minimum supported server Windows 10 Build 20348
Header directml.h