aclnnGridSampler3D
Applicable Products
| Product | Supported |
|---|---|
| √ | |
| √ | |
| √ | |
| × | |
| × | |
| √ |
Function
Operator function: Given an input tensor input and a corresponding grid, the operator fills the pixel values from the corresponding positions in input into the positions specified by the grid based on the coordinate information provided at each grid position, producing the final output.
Formula:
The dimensions of input, grid, and output are as follows:
Where N in input, grid, and output is consistent, C in input and output is consistent, , , in grid and output are consistent, and the last dimension of grid has a size of 3, indicating that the input pixel position information is (x, y, z), with the value ranges of x, y, and z normalized to [-1, 1].
- For out-of-range coordinates, different processing is applied based on paddingMode:
- paddingMode=0 indicates that out-of-bounds positions are filled with 0.
- paddingMode=1 indicates that out-of-bounds positions are filled with boundary values.
- paddingMode=2 indicates that out-of-bounds positions are filled with the symmetric values of boundary values.
- When sampling input, different processing is performed based on interpolationMode:
- interpolationMode="bilinear" indicates taking the weighted average of the eight coordinates around (x, y, z) in input.
- interpolationMode="nearest" indicates taking the coordinate value closest to (x, y, z) in input.
Function Prototype
Each operator is divided into a two-phase API. You must first call the "aclnnGridSampler3DGetWorkspaceSize" API to obtain the workspace size required for computation and the executor that includes the operator computation process, and then call the "aclnnGridSampler3D" API to execute the computation.
aclnnStatus aclnnGridSampler3DGetWorkspaceSize(
const aclTensor *input,
const aclTensor *grid,
int64_t interpolationMode,
int64_t paddingMode,
bool alignCorners,
aclTensor *out,
uint64_t *workspaceSize,
aclOpExecutor **executor)aclnnStatus aclnnGridSampler3D(
void *workspace,
uint64_t workspaceSize,
aclOpExecutor *executor,
aclrtStream stream)aclnnGridSampler3DGetWorkspaceSize
Parameters
Parameter Name Input/Output Description Usage Description Data Type Data Format Dimensions (shape) Non-contiguous Tensor input (aclTensor*) Input Input tensor for interpolation computation, corresponding to `input` described in the formula. - Supports empty tensor.
- When the data format is ND, it is processed in NCDHW format; NDHWC is supported only when the conditions are met (data type is FLOAT32 && interpolationMode is 0 && the C axis size is a multiple of 4).
FLOAT16, FLOAT32, DOUBLE, BFLOAT16 NCDHW, NDHWC, ND 5 √ grid (aclTensor*) input The sampling grid, corresponding to the `grid` described in the formula. - Supports empty tensor.
- The data type is consistent with the data type of the input parameter `input`.
- Supports shape (N, Dout, Hout, Wout, 3), where N is consistent with N in the shape of the input parameter `input`.
FLOAT16, FLOAT32, DOUBLE, BFLOAT16 ND 5 √ interpolationMode (int64_t) Input Indicates the interpolation mode, corresponding to `interpolationMode` in the formula description. Supports two modes: 0: bilinear, 1: nearest. - - - - paddingMode (int64_t) Input Indicates the out-of-bounds grid padding mode. That is, when the grid contains values outside the [-1, 1] range, the corresponding output is processed according to the method defined by paddingMode. Corresponds to `paddingMode` in the formula description. Supports three modes: 0: zeros, 1: border, 2: reflection. - - - - alignCorners (bool) Input Specifies how feature map coordinates correspond to feature values. If True, the extreme values -1 and 1 are treated as the centers of the corner pixels of the reference input. If False, they are treated as the corners of the corner pixels of the reference input. - - - - out (aclTensor*) Output Final output result of the interpolation computation, corresponding to the `output` described in the formula. - Supports empty tensor.
- The data format and data type are consistent with input.
- The N axis and C axis of the shape are consistent with input, and the D axis, H axis, and W axis of the shape are consistent with grid.
FLOAT16, FLOAT32, DOUBLE, BFLOAT16 NCDHW, NDHWC, ND 5 √ workspaceSize (uint64_t*) output Returns the workspace size to be applied for on the Device side. - - - - - executor (aclOpExecutor**) Output Returns the op executor, which includes the operator computation process. - - - - - Atlas training products :The data type of parameters
input,grid, andoutdoes not support BFLOAT16.
Return Value
aclnnStatus: return code. For details, see aclnn Return Codes.
The first-phase API completes input parameter validation and reports an error in the following scenarios:
Return Code Error Code Description ACLNN_ERR_PARAM_NULLPTR 161001 The input, grid, or out passed in is a null pointer. ACLNN_ERR_PARAM_INVALID 161002 The data type of input, grid, or out is not within the supported range, or the data types are inconsistent. The data format of input, grid, or out is not within the supported range. The value of interpolationMode or paddingMode is not within the supported range. The dimension relationship among input, grid, and out does not match.
aclnnGridSampler3D
Parameters
Parameter Name Input/Output Description workspace Input The workspace memory address applied on the Device side. workspaceSize Input Size of the workspace applied on the Device side, obtained by the first-phase API aclnnGridSampler3DGetWorkspaceSize. executor Input Operator executor, which includes the operator computation flow. stream Input Specifies the Stream on which the task is executed. Return Value
aclnnStatus: return status code. For details, see aclnn Return Codes.
Constraints
- The input
inputmust satisfy . - Deterministic computation:
- aclnnGridSampler3D uses deterministic implementation by default.
Example of Calling
The sample code is as follows, for reference only. For the specific compilation and execution process, see Compile and Run Samples.
#include <iostream>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_grid_sampler3d.h"
#define CHECK_RET(cond, return_expr) \
do { \
if (!(cond)) { \
return_expr; \
} \
} while (0)
#define LOG_PRINT(message, ...) \
do { \
printf(message, ##__VA_ARGS__); \
} while (0)
int64_t GetShapeSize(const std::vector<int64_t> &shape)
{
int64_t shapeSize = 1;
for (auto i : shape) {
shapeSize *= i;
}
return shapeSize;
}
int Init(int32_t deviceId, aclrtStream *stream)
{
// Standard pattern for resource initialization.
auto ret = aclInit(nullptr);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret);
ret = aclrtSetDevice(deviceId);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret);
ret = aclrtCreateStream(stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret);
return 0;
}
template <typename T>
int CreateAclTensor(const std::vector<T> &hostData, const std::vector<int64_t> &shape, void **deviceAddr,
aclDataType dataType, aclTensor **tensor)
{
auto size = GetShapeSize(shape) * sizeof(T);
// Call aclrtMalloc to apply for device-side memory.
auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
// Call aclrtMemcpy to copy host-side data to device-side memory.
ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
// Compute the strides of the contiguous tensor.
std::vector<int64_t> strides(shape.size(), 1);
for (int64_t i = shape.size() - 2; i >= 0; i--) {
strides[i] = shape[i + 1] * strides[i + 1];
}
// Call the aclCreateTensor API to create an aclTensor.
*tensor = aclCreateTensor(shape.data(),
shape.size(),
dataType,
strides.data(),
0,
aclFormat::ACL_FORMAT_NCDHW,
shape.data(),
shape.size(),
*deviceAddr);
return 0;
}
int main()
{
// 1. (Boilerplate) Initialize the device/stream. See the ACL API manual.
// Fill in the deviceId based on your actual device.
int32_t deviceId = 0;
aclrtStream stream;
auto ret = Init(deviceId, &stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
// 2. Construct the input and output. Customize the construction based on the API.
int64_t interpolationMode = 0;
int64_t paddingMode = 0;
bool alignCorners = false;
std::vector<int64_t> inputShape = {1, 1, 1, 3, 3};
std::vector<int64_t> gridShape = {1, 1, 2, 2, 3};
std::vector<int64_t> outShape = {1, 1, 1, 2, 2};
void *inputDeviceAddr = nullptr;
void *gridDeviceAddr = nullptr;
void *outDeviceAddr = nullptr;
aclTensor *input = nullptr;
aclTensor *grid = nullptr;
aclTensor *out = nullptr;
std::vector<float> inputHostData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<float> gridHostData = {-1, -1, 0, -1, 1, -1, -1, 0, 0, 0, 1, 0};
std::vector<float> outHostData = {0, 0, 0, 0};
// Create the input aclTensor.
ret = CreateAclTensor(inputHostData, inputShape, &inputDeviceAddr, aclDataType::ACL_FLOAT, &input);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create the grid aclTensor.
ret = CreateAclTensor(gridHostData, gridShape, &gridDeviceAddr, aclDataType::ACL_FLOAT, &grid);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create the output aclTensor.
ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// 3. Call the CANN operator library API. Replace with the specific API name.
uint64_t workspaceSize = 0;
aclOpExecutor *executor;
// Call the first-phase API of aclnnGridSampler3D.
ret = aclnnGridSampler3DGetWorkspaceSize(
input, grid, interpolationMode, paddingMode, alignCorners, out, &workspaceSize, &executor);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnGridSampler3DGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
// Apply for device memory based on the workspaceSize calculated by the first-phase API.
void *workspaceAddr = nullptr;
if (workspaceSize > 0) {
ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret);
}
// Call the second-phase API of aclnnGridSampler3D.
ret = aclnnGridSampler3D(workspaceAddr, workspaceSize, executor, stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnGridSampler3D failed. ERROR: %d\n", ret); return ret);
// 4. (Boilerplate) Synchronously wait for task execution to complete.
ret = aclrtSynchronizeStream(stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
// 5. Obtain the output value and copy the result from the device side memory to the host side. Modify based on the specific API definition.
auto size = GetShapeSize(outShape);
std::vector<float> resultData(size, 0);
ret = aclrtMemcpy(resultData.data(),
resultData.size() * sizeof(resultData[0]),
outDeviceAddr,
size * sizeof(resultData[0]),
ACL_MEMCPY_DEVICE_TO_HOST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy resultData from device to host failed. ERROR: %d\n", ret);
return ret);
for (int64_t i = 0; i < size; i++) {
LOG_PRINT("resultData[%ld] is: %f\n", i, resultData[i]);
}
// 6. Release aclTensor. Modify based on the specific API definition.
aclDestroyTensor(input);
aclDestroyTensor(grid);
aclDestroyTensor(out);
// 7. Release device resources. Modify based on the specific API definition as needed.
aclrtFree(inputDeviceAddr);
aclrtFree(gridDeviceAddr);
aclrtFree(outDeviceAddr);
if (workspaceSize > 0) {
aclrtFree(workspaceAddr);
}
aclrtDestroyStream(stream);
aclrtResetDevice(deviceId);
aclFinalize();
return 0;
}