<!--
{
  "availability" : [
    "iOS: 14.0.0 - 18.0.0",
    "iPadOS: 14.0.0 - 18.0.0",
    "macCatalyst: 14.0.0 - 18.0.0",
    "macOS: 11.0.0 - 15.0.0",
    "tvOS: 14.0.0 - 18.0.0",
    "visionOS: 1.0.0 - 2.0.0",
    "watchOS: 7.0.0 - 11.0.0"
  ],
  "documentType" : "symbol",
  "framework" : "Accelerate",
  "identifier" : "/documentation/Accelerate/BNNSFilterCreateLayerPooling(_:_:)",
  "metadataVersion" : "0.1.0",
  "role" : "Function",
  "symbol" : {
    "kind" : "Function",
    "modules" : [
      "Accelerate"
    ],
    "preciseIdentifier" : "c:@F@BNNSFilterCreateLayerPooling"
  },
  "title" : "BNNSFilterCreateLayerPooling(_:_:)"
}
-->

# BNNSFilterCreateLayerPooling(_:_:)

Returns a new pooling layer.

```
func BNNSFilterCreateLayerPooling(_ layer_params: UnsafePointer<BNNSLayerParametersPooling>, _ filter_params: UnsafePointer<BNNSFilterParameters>?) -> BNNSFilter?
```

## Parameters

`layer_params`

Layer parameters.

`filter_params`

The filter runtime parameters.

## Discussion

Use a pooling layer to downsample an input, selecting, for example, the average or the maximum value in a specified kernel size. The following figure illustrates how a 2 x 2 maximum pooling kernel samples each 2 x 2 block of values of 4 x 4 source. The highlighted block contains the values `[3, 4, 0, 0]`, so the maximum value passed to the destination element in `output` is `4`.

![Figure that shows a two dimensional four times four source matrix downsampled using a two times two pooling kernel that returns a three times three result. The operation writes the maximum value of each two times two block from the source matrix to the result.](images/com.apple.accelerate/media-3633103@2x.png)

The following code shows how you apply pooling to the input in the above figure. Note that the input is a 2 x 2 x 1 [`BNNSDataLayoutImageCHW`](/documentation/Accelerate/BNNSDataLayoutImageCHW) tensor. Definie [`x_padding`](/documentation/Accelerate/BNNSLayerParametersPooling/x_padding) and [`y_padding`](/documentation/Accelerate/BNNSLayerParametersPooling/y_padding) as 1 to add zero padding:

```swift
let input: [Float] = [1, 2,
                      3, 4]

var output = [Float](repeating: 0, count: 9)

let inDescriptor = BNNSNDArrayDescriptor(flags: BNNSNDArrayFlags(0),
                                         layout: BNNSDataLayoutImageCHW,
                                         size: (2, 2, 1, 0, 0, 0, 0, 0),
                                         stride: (0, 0, 0, 0, 0, 0, 0, 0),
                                         data: nil,
                                         data_type: .float,
                                         table_data: nil,
                                         table_data_type: .float,
                                         data_scale: 0,
                                         data_bias: 0)

let outDescriptor = BNNSNDArrayDescriptor(flags: BNNSNDArrayFlags(0),
                                          layout: BNNSDataLayoutImageCHW,
                                          size: (3, 3, 1, 0, 0, 0, 0, 0),
                                          stride: (0, 0, 0, 0, 0, 0, 0, 0),
                                          data: nil,
                                          data_type: .float,
                                          table_data: nil,
                                          table_data_type: .float,
                                          data_scale: 0,
                                          data_bias: 0)

var parameters = BNNSLayerParametersPooling(i_desc: inDescriptor,
                                            o_desc: outDescriptor,
                                            bias: BNNSNDArrayDescriptor(),
                                            activation: .identity,
                                            pooling_function: .max    ,
                                            k_width: 2,
                                            k_height: 2,
                                            x_stride: 1,
                                            y_stride: 1,
                                            x_dilation_stride: 0,
                                            y_dilation_stride: 0,
                                            x_padding: 1,
                                            y_padding: 1,
                                            pad: (0, 0, 0, 0))

let filter = BNNSFilterCreateLayerPooling(&parameters, nil)

defer {
    BNNSFilterDestroy(filter)
}

BNNSPoolingFilterApplyBatch(filter, 1,
                            input, input.count,
                            &output, output.count,
                            nil, 0)
```

On return, `output` contains the following values:

```swift
[ 1.0, 2.0, 2.0, 
  3.0, 4.0, 4.0, 
  3.0, 4.0, 4.0 ]
```

### UnMax Pooling

Use [`BNNSPoolingFunctionUnMax`](/documentation/Accelerate/BNNSPoolingFunctionUnMax) in conjunction with the indices generated by [`BNNSPoolingFunctionMax`](/documentation/Accelerate/BNNSPoolingFunctionMax) to partially recreate the original data of a maximum pooling operation. UnMax pooling is a partial inverse of maximum pooling that sets all non-maximal values to zero.

For example, given the following input data:

```swift
let input: [Float] = [1, 1, 1, 9,
                      1, 9, 9, 1,
                      1, 1, 1, 1,
                      1, 9, 1, 9]
```

Use [`BNNSPoolingFilterApplyBatch(_:_:_:_:_:_:_:_:)`](/documentation/Accelerate/BNNSPoolingFilterApplyBatch(_:_:_:_:_:_:_:_:)) to perform the maximum pooling and populate an indices array with positional information of maximum elements in each window:

```swift
var output = [Float](repeating: 0, count: 3 * 3)

let inDescriptor = BNNSNDArrayDescriptor(flags: BNNSNDArrayFlags(0),
                                         layout: BNNSDataLayoutImageCHW,
                                         size: (4, 4, 1, 0, 0, 0, 0, 0),
                                         stride: (0, 0, 0, 0, 0, 0, 0, 0),
                                         data: nil,
                                         data_type: .float,
                                         table_data: nil,
                                         table_data_type: .float,
                                         data_scale: 0,
                                         data_bias: 0)

let outDescriptor = BNNSNDArrayDescriptor(flags: BNNSNDArrayFlags(0),
                                          layout: BNNSDataLayoutImageCHW,
                                          size: (3, 3, 1, 0, 0, 0, 0, 0),
                                          stride: (0, 0, 0, 0, 0, 0, 0, 0),
                                          data: nil,
                                          data_type: .float,
                                          table_data: nil,
                                          table_data_type: .float,
                                          data_scale: 0,
                                          data_bias: 0)

var parameters = BNNSLayerParametersPooling(i_desc: inDescriptor,
                                            o_desc: outDescriptor,
                                            bias: BNNSNDArrayDescriptor(),
                                            activation: .identity,
                                            pooling_function: .max    ,
                                            k_width: 2,
                                            k_height: 2,
                                            x_stride: 1,
                                            y_stride: 1,
                                            x_dilation_stride: 0,
                                            y_dilation_stride: 0,
                                            x_padding: 0,
                                            y_padding: 0,
                                            pad: (0, 0, 0, 0))

let filter = BNNSFilterCreateLayerPooling(&parameters, nil)

defer {
    BNNSFilterDestroy(filter)
}

var indices = [Int](repeating: 0, count: input.count)

BNNSPoolingFilterApplyBatch(filter, 1,
                            input, input.count,
                            &output, output.count,
                            &indices, indices.count)
```

To perform the UnMax pooling, reuse the parameters structure, but swap the input and output descriptors:

```swift
var recreatedInput = [Float](repeating: 0, count: input.count)

parameters.i_desc = outDescriptor
parameters.o_desc = inDescriptor
parameters.pooling_function = BNNSPoolingFunctionUnMax

let unMaxFilter = BNNSFilterCreateLayerPooling(&parameters, nil)

defer {
    BNNSFilterDestroy(unMaxFilter)
}

BNNSPoolingFilterApplyBatch(unMaxFilter, 1,
                            output, output.count,
                            &recreatedInput, recreatedInput.count,
                            &indices, indices.count)
```

On return, `recreatedInput` is similar to `input`, but the non-maximal values are zero:

```swift
[ 0.0, 0.0, 0.0, 9.0,
  0.0, 9.0, 9.0, 0.0,
  0.0, 0.0, 0.0, 0.0,
  0.0, 9.0, 0.0, 9.0 ]
```

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)