aclnnUpsampleTrilinear3d
Applicable Products
| Product | Supported |
|---|---|
| × | |
| √ | |
| √ | |
| × | |
| √ | |
| √ |
Function
- Description: Applies the trilinear interpolation algorithm to upsample an input signal consisting of multiple input channels.
- Formula:
- Core algorithm logic:
- Map each point of the target image back to the source image to obtain a coordinate with decimal fractions.
- Based on this floating-point coordinate, calculate the adjacent points in the original image.
- Calculate the weights from each adjacent point to the target point, and perform weighted summation to obtain the target point value.
- Specific calculation logic:
The scaling mode is divided into corner-aligned and edge-aligned. Corner-aligned means alignment is based on the top-left pixel center of the original image, while edge-aligned means alignment is based on the top-left vertex and two edges of the original image. Differences exist in the calculation of scaling factors and coordinate positions. For a 3D interpolation point , the following formulas apply:
Therefore, for a point p(x,y,z) in a certain direction of the output, the point mapped back to the original image is denoted as q(x',y',z'), and the relationship is:
Denote:
The following formula applies:
- Core algorithm logic:
Function Prototype
Each operator is divided into a two-phase API. You must first call the "aclnnUpsampleTrilinear3dGetWorkspaceSize" API to obtain the workspace size required for computation and the executor that contains the operator computation process, and then call the "aclnnUpsampleTrilinear3d" API to execute the computation.
aclnnStatus aclnnUpsampleTrilinear3dGetWorkspaceSize(
const aclTensor *self,
const aclIntArray *outputSize,
bool alignCorners,
double scalesD,
double scalesH,
double scalesW,
aclTensor *out,
uint64_t *workspaceSize,
aclOpExecutor **executor)aclnnStatus aclnnUpsampleTrilinear3d(
void *workspace,
uint64_t workspaceSize,
aclOpExecutor *executor,
aclrtStream stream)aclnnUpsampleTrilinear3dGetWorkspaceSize
Parameters
Parameter Name Input/Output Description Description Data Type Data Format Dimension (shape) Non-contiguous Tensor self (aclTensor*) Input Represents the input tensor for upsampling, corresponding to `self` in the formula. - Empty tensors are not supported.
- When the data format is ND, it is processed as NCDHW by default.
- The values of the C, D, H, and W axes of the shape must be greater than 0.
FLOAT32, FLOAT16, BFLOAT16, DOUBLE NCDHW, NDHWC, ND 5 √ outputSize (aclIntArray*) Input Indicates the spatial size of the output parameter `out` in the D, H, and W dimensions, corresponding to `outputSize` in the formula. The size is 3, and each element is greater than zero. INT64 - - - alignCorners (bool) Input Indicates whether to align corner pixels, corresponding to `alignCorners` in the formula. If set to true, the corner pixels of the input and output tensors are aligned; otherwise, they are not aligned. - - - - scalesD (double) Input Indicates the depth dimension multiplier for the output `out`, corresponding to `scales_d` in the formula. The value must be less than or equal to 50. - - - - scalesH (double) Input Represents the multiplier for the height dimension of the output `out`, corresponding to `scales_h` in the formula. The value must be less than or equal to 50. - - - - scalesW (double) Input Represents the multiplier for the width dimension of the output `out`, corresponding to `scales_w` in the formula. The value must be less than or equal to 50. - - - - out (aclTensor*) Output Represents the output tensor after sampling. - Empty tensors are not supported.
- The data type and data format must be consistent with the input parameter `self`.
- The N and C axes of the shape must be consistent with the input parameter `self`.
FLOAT32, FLOAT16, BFLOAT16, DOUBLE NCDHW, NDHWC, ND 5 √ workspaceSize (uint64_t*) Output Returns the workspace size to be allocated on the Device side. - - - - - executor (aclOpExecutor**) Output Returns the operator executor, which contains the operator computation process. - - - - - Atlas inference products :- The data type of the input parameter
selfonly supports FLOAT32 and FLOAT16, and does not support inf or -inf inputs. - The data type of the output parameter
outonly supports FLOAT32 and FLOAT16.
- The data type of the input parameter
Atlas training products :The data types of the input parameter
selfand output parameteroutsupport FLOAT32, FLOAT16, and DOUBLE.
Return Value
aclnnStatus: return status code. For details, see aclnn Return Codes.
The first-phase API performs input parameter validation and reports an error in the following scenarios:
Return Code Error Code Description ACLNN_ERR_PARAM_NULLPTR 161001 When the passed self, outputSize, or out is a null pointer. ACLNN_ERR_PARAM_INVALID 161002 When the data type of self is not within the supported range, or the data type of self differs from that of out. When the shape of self is not 5-dimensional. The size of outputSize is not equal to 3. The size of self in the C, D, H, or W dimension is not greater than 0. An element value in outputSize is not greater than 0.
aclnnUpsampleTrilinear3d
Parameters
Parameter Name Input/Output Description workspace Input Workspace memory address applied for on the Device side. workspaceSize Input Size of the workspace to be applied for on the Device side, obtained through the first-phase API aclnnUpsampleTrilinear3dGetWorkspaceSize. executor Input Operator executor, which encapsulates the operator computation flow. stream Input Specifies the stream for executing the task. Return Value
aclnnStatus: return status code. For details, see aclnn Return Codes.
Constraints
In the input data scaling scenario, the reduction factor must be less than or equal to 50, that is:
Shape constraints for parameters
selfandout:- The value of each dimension must be less than or equal to 2^20.
- The N and C axes of the parameter
outmust remain consistent with those ofself. - The memory usage must be less than 60 GB. The memory usage calculation formula is as follows:
Where:
- N represents the N axis of the input and output.
- C represents the C axis of the input and output.
- N * C * self_D * self_H < 2^31
- out_W * out_H < 2^31
The parameters self, outputSize, scalesD, scalesH, and scalesW must satisfy the following constraints:
Deterministic computation:
- aclnnUpsampleTrilinear3d uses deterministic implementation by default.
Example
The following sample code is for reference only. For details about compilation and running, see Compile and Run Samples.
#include <iostream>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_upsample_trilinear_3d.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 shape_size = 1;
for (auto i : shape) {
shape_size *= i;
}
return shape_size;
}
int Init(int32_t deviceId, aclrtStream *stream)
{
// Boilerplate, 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 data from host to device 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 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 aclCreateTensor 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 device/stream. See the ACL API manual.
// Set deviceId based on the actual device.
int32_t deviceId = 0;
aclrtStream stream;
auto ret = Init(deviceId, &stream);
// Handle check as needed.
CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
// 2. Construct the input and output. Customize the construction based on the API.
std::vector<int64_t> selfShape = {1, 1, 2, 2, 2};
std::vector<int64_t> outShape = {1, 1, 4, 4, 4};
void *selfDeviceAddr = nullptr;
void *outDeviceAddr = nullptr;
aclTensor *self = nullptr;
aclTensor *out = nullptr;
std::vector<float> selfHostData = {1, 2, 3, 4, 5, 6, 7, 8};
const size_t kSize64 = 64U;
std::vector<float> outHostData(kSize64, 0);
std::vector<int64_t> outputSizeData = {4, 4, 4};
bool alignCorners = false;
double scalesD = 0.0;
double scalesH = 0.0;
double scalesW = 0.0;
// Create the self aclTensor.
ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create the out aclTensor.
ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out);
CHECK_RET(ret == ACL_SUCCESS, return ret);
const aclIntArray *outputSize = aclCreateIntArray(outputSizeData.data(), outputSizeData.size());
CHECK_RET(outputSize != nullptr, return ACL_ERROR_INTERNAL_ERROR);
// 3. Call the CANN operator library API. Replace with the specific API as needed.
uint64_t workspaceSize = 0;
aclOpExecutor *executor;
// Call the first-phase API of aclnnUpsampleTrilinear3d.
ret = aclnnUpsampleTrilinear3dGetWorkspaceSize(
self, outputSize, alignCorners, scalesD, scalesH, scalesW, out, &workspaceSize, &executor);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnUpsampleTrilinear3dGetWorkspaceSize failed. ERROR: %d\n", ret);
return ret);
// Apply for device memory based on the workspaceSize computed 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 aclnnUpsampleTrilinear3d.
ret = aclnnUpsampleTrilinear3d(workspaceAddr, workspaceSize, executor, stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnUpsampleTrilinear3d 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 device memory to host memory. 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(float),
ACL_MEMCPY_DEVICE_TO_HOST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
for (int64_t i = 0; i < size; i++) {
LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]);
}
// 6. Release aclTensor and aclScalar. Modify based on the specific API definition.
aclDestroyTensor(self);
aclDestroyTensor(out);
// 7. Release device resources. Modify based on the API definition of the specific API.
aclrtFree(selfDeviceAddr);
aclrtFree(outDeviceAddr);
if (workspaceSize > 0) {
aclrtFree(workspaceAddr);
}
aclrtDestroyStream(stream);
aclrtResetDevice(deviceId);
aclFinalize();
return 0;
}