aclnnAvgPool3d
Applicable Products
| Product | Supported |
|---|---|
| √ | |
| √ | |
| √ | |
| × | |
| √ | |
| × |
Function
Description: Performs 3D average pooling on the input tensor with a window of and a stride of , where is kernelSize, representing the size of the pooling window, and is stride, representing the stride of the pooling operation.
Formula:
The relationship between the input(), output out(), pooling stride(), and pooling window size kernelSize() is:
Function Prototype
Each operator is divided into a two-phase API. The "aclnnAvgPool3dGetWorkspaceSize" API must be called first to obtain the workspace size required for computation and the executor that encapsulates the operator computation flow. Then, the "aclnnAvgPool3d" API is called to perform the computation.
aclnnStatus aclnnAvgPool3dGetWorkspaceSize(
const aclTensor *self,
const aclIntArray *kernelSize,
const aclIntArray *strides,
const aclIntArray *padding,
bool ceilMode,
bool countIncludePad,
int64_t divisorOverride,
aclTensor *out,
uint64_t *workspaceSize,
aclOpExecutor **executor)aclnnStatus aclnnAvgPool3d(
void *workspace,
uint64_t workspaceSize,
aclOpExecutor *executor,
aclrtStream stream)aclnnAvgPool3dGetWorkspaceSize
Parameters:
Parameter Input/Output Description Instruction Data Type Data Format Dimension (Shape) Non-contiguous Tensor self Input The input in the forward process, corresponding to input in the formula. - FLOAT32, FLOAT16, BFLOAT16 ND 4-5 √ kernelSize Input Size of the pooling window, which is k in the formula. Length of 1 (KD = KH = KW) or 3 (KD, KH, KW). The value must be greater than 0 and less than or equal to the size of self in the corresponding D, H, W dimensions. INT64 - - - strides Input Stride of the pooling operation, i.e., strides in the formula. Length of 0 (the values are the same as kernelSize), 1 (SD = SH = SW), or 3 (SD, SH, SW). When the length is 1 or 3, the values must be greater than 0. INT64 - - - padding Input Number of zero-padding layers in the D, H, and W directions of the input, represented as paddings in the formula. Length of 1 (PD = PH = PW) or 3 (PD, PH, PW), with values in the range [0, kernelSize/2]. INT64 - - - ceilMode Input Whether the shape of the deduced output out is rounded up. - BOOL - - - countIncludePad Input Specifies whether to include the zeros padded by padding when computing average pooling. - BOOL - - - divisorOverride Input Divisor used for averaging. When the value is 0, this attribute does not take effect. INT64 - - - out Output The output tensor. - FLOAT32, FLOAT16, BFLOAT16 ND 4-5 √ workspaceSize output Returns the workspace size to be applied for on the Device side. - - - - - executor Output Returns the op executor, which contains the operator computation process. - - - - - Atlas inference products : The data type of the self and out parameters does not support BFLOAT16.
Return value:
aclnnStatus: return code. For details, see aclnn Return Code.
The first-phase API performs input parameter validation and returns an error in the following scenarios:
Return Code Error Code Description ACLNN_ERR_PARAM_NULLPTR 161001 The self, kernelSize, stride, padding, or out passed in is a null pointer. ACLNN_ERR_PARAM_INVALID 161002 The data type or data format of self or out passed in is not within the supported range. The data type or data format of self and out passed in is inconsistent. A value in a dimension of the passed stride is less than or equal to 0, or a padding value is outside the range [0, kernelSize/2]. A value in a dimension of the passed kernelSize is less than or equal to 0, or exceeds the value of the corresponding dimension of self. The length of the passed kernelSize or padding is neither 1 nor 3, or the length of stride is neither 0, 1, nor 3. The output shape computed based on the average pooling semantics is inconsistent with the output shape passed to the API.
aclnnAvgPool3d
Parameters:
Parameter Input/Output Description workspace Input Address of the workspace memory applied for on the Device side. workspaceSize Input Size of the workspace applied for on the Device side, obtained through the first-phase API aclnnAvgPool3dGetWorkspaceSize. executor Input Operator executor, which contains the operator computation flow. stream Input Specifies the stream on which the task is executed. Return value
aclnnStatus: return code. For details, see aclnn Return Code.
Constraints
Deterministic computation:
- aclnnAvgPool3d defaults to a deterministic implementation.
Example
The following provides example code for reference only. For details about compilation and running, see Compile and Run Samples.
#include <cstdio>
#include <iostream>
#include <memory>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_avgpool3d.h"
#define CHECK_RET(cond, return_expr) \
do { \
if (!(cond)) { \
return_expr; \
} \
} while (0)
#define CHECK_FREE_RET(cond, return_expr) \
do { \
if (!(cond)) { \
Finalize(deviceId, stream); \
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) {
// 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 the host side to the 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);
// Calculate the stride of a contiguous tensor.
std::vector<int64_t> stride(shape.size(), 1);
for (int64_t i = shape.size() - 2; i >= 0; i--) {
stride[i] = shape[i + 1] * stride[i + 1];
}
// Call the aclCreateTensor API to create an aclTensor.
*tensor = aclCreateTensor(shape.data(), shape.size(), dataType, stride.data(), 0, aclFormat::ACL_FORMAT_ND,
shape.data(), shape.size(), *deviceAddr);
return 0;
}
void Finalize(int32_t deviceId, aclrtStream stream)
{
aclrtDestroyStream(stream);
aclrtResetDevice(deviceId);
aclFinalize();
}
int aclnnAvgPool3dTest(int32_t deviceId, aclrtStream& stream) {
auto ret = Init(deviceId, &stream);
CHECK_FREE_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
// 2. Construct the input and output. Custom construction is required based on the API interface.
int64_t divisorOverride = 0;
bool countIncludePad = true;
bool ceilMode = false;
std::vector<int64_t> selfShape = {1, 16, 4, 4, 4};
std::vector<int64_t> outShape = {1, 16, 1, 1, 1};
std::vector<int64_t> kernelDims = {4, 4, 4};
std::vector<int64_t> strideDims = {1, 1, 1};
std::vector<int64_t> paddingDims = {0, 0, 0};
void* selfDeviceAddr = nullptr;
void* outDeviceAddr = nullptr;
aclTensor* self = nullptr;
aclTensor* out = nullptr;
std::vector<float> selfHostData(1024, 2);
std::vector<float> outHostData(16, 0);
// Create the self aclTensor.
ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self);
std::unique_ptr<aclTensor, aclnnStatus (*)(const aclTensor *)> selfTensorPtr(self, aclDestroyTensor);
std::unique_ptr<void, aclError (*)(void *)> selfDeviceAddrPtr(selfDeviceAddr, aclrtFree);
CHECK_FREE_RET(ret == ACL_SUCCESS, return ret);
// Create the kernel aclIntArray.
aclIntArray *kernelSize = aclCreateIntArray(kernelDims.data(), 3);
CHECK_FREE_RET(kernelSize != nullptr, return ACL_ERROR_INTERNAL_ERROR);
// Create the stride aclIntArray.
aclIntArray *stride = aclCreateIntArray(strideDims.data(), 3);
CHECK_FREE_RET(stride != nullptr, return ACL_ERROR_INTERNAL_ERROR);
// Create the padding aclIntArray.
aclIntArray *padding = aclCreateIntArray(paddingDims.data(), 3);
CHECK_FREE_RET(padding != nullptr, return ACL_ERROR_INTERNAL_ERROR);
// Create the out aclTensor.
ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out);
std::unique_ptr<aclTensor, aclnnStatus (*)(const aclTensor *)> outTensorPtr(out, aclDestroyTensor);
std::unique_ptr<void, aclError (*)(void *)> outDeviceAddrPtr(outDeviceAddr, aclrtFree);
CHECK_FREE_RET(ret == ACL_SUCCESS, return ret);
// 3. Call the CANN operator library API. Replace with the actual API name.
uint64_t workspaceSize = 0;
aclOpExecutor* executor;
// Call the first-phase API of aclnnAvgPool3d.
ret = aclnnAvgPool3dGetWorkspaceSize(self,
kernelSize,
stride,
padding,
ceilMode,
countIncludePad,
divisorOverride,
out,
&workspaceSize,
&executor);
CHECK_FREE_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAvgPool3dGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
// Apply for device memory based on the workspaceSize calculated by the first-phase API.
void* workspaceAddr = nullptr;
std::unique_ptr<void, aclError (*)(void *)> workspaceAddrPtr(nullptr, aclrtFree);
if (workspaceSize > 0) {
ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
CHECK_FREE_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret);
workspaceAddrPtr.reset(workspaceAddr);
}
// Call the second-phase API of aclnnAvgPool3d.
ret = aclnnAvgPool3d(workspaceAddr, workspaceSize, executor, stream);
CHECK_FREE_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAvgPool3d failed. ERROR: %d\n", ret); return ret);
// 4. (Boilerplate) Synchronously wait for task execution to complete.
ret = aclrtSynchronizeStream(stream);
CHECK_FREE_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 memory to the host memory. Modify this step based on the specific API definition.
auto size = GetShapeSize(outShape);
std::vector<float> outData(size, 0);
ret = aclrtMemcpy(outData.data(), outData.size() * sizeof(outData[0]), outDeviceAddr,
size * sizeof(outData[0]), ACL_MEMCPY_DEVICE_TO_HOST);
CHECK_FREE_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("out result[%ld] is: %f\n", i, outData[i]);
}
return ACL_SUCCESS;
}
int main() {
// 1. (Boilerplate) Initialize the device/stream. Refer to the ACL API manual.
// Fill in the deviceId based on your actual device.
int32_t deviceId = 0;
aclrtStream stream;
auto ret = aclnnAvgPool3dTest(deviceId, stream);
CHECK_FREE_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAvgPool3dTest failed. ERROR: %d\n", ret); return ret);
Finalize(deviceId, stream);
return 0;
}