# How ncnn Mat Reshape Works: Zero-Copy Tensor Views and the 4 Method Overloads

> Explore ncnn Mat reshape zero copy views and four method overloads. Learn how ncnn efficiently reshapes tensors without memory allocation for contiguous data.

- Repository: [Tencent/ncnn](https://github.com/tencent/ncnn)
- Tags: internals
- Published: 2026-02-23

---

**The ncnn::Mat class performs tensor reshaping without allocating new memory when the layout is contiguous, returning lightweight views that share the original buffer; however, if the tensor has a non-contiguous layout (such as channel-aligned padding), it performs a per-channel memory copy to ensure data integrity.**

Tensor reshaping is a fundamental operation in deep learning inference. In the Tencent/ncnn framework, the `ncnn::Mat` class serves as the core multi-dimensional array container, providing specialized reshape capabilities optimized for mobile and embedded deployments. Understanding how ncnn Mat reshape operations handle memory layouts is essential for writing efficient, zero-copy inference pipelines that minimize overhead.

## Core Implementation of ncnn Mat Reshaping

The reshaping logic is implemented in **[`src/mat.cpp`](https://github.com/Tencent/ncnn/blob/main/src/mat.cpp)** (lines 60‑120) with declarations in **[`src/mat.h`](https://github.com/Tencent/ncnn/blob/main/src/mat.h)** (lines 1400‑1460). All four overloads follow a consistent validation and execution pattern designed to maximize performance while preventing data corruption.

The implementation first validates that the product of source dimensions (`w * h * d * c`) equals the product of the requested target dimensions. If this validation fails, the function immediately returns an empty `Mat`. This ensures that reshaping never changes the total element count, maintaining tensor integrity throughout the operation.

### Handling Non-Contiguous Layouts

When the source tensor has three or more dimensions (`dims >= 3`) and its internal **`cstep`** value does not equal `w * h * d` (indicating channel-aligned padding or SIMD packing), ncnn cannot create a simple view. Instead, it allocates a new `Mat` with the requested shape and performs a per-channel copy:

```cpp
for (int i = 0; i < c; i++) {
    const void* ptr = (unsigned char*)data + i * cstep * elemsize;
    void* mptr = (unsigned char*)m.data + i * (size_t)w * h * d * elemsize;
    memcpy(mptr, ptr, (size_t)w * h * d * elemsize);
}

```

This flattening operation ensures that the resulting tensor has a contiguous layout matching the new shape, preventing the reinterpretation of alignment bytes as actual data.

### Fast Path for Contiguous Tensors

If the source layout is already contiguous (`cstep == w * h * d`), ncnn Mat reshape takes a zero‑copy approach. The function creates a lightweight view by copying the current object (`Mat m = *this`), updating the dimension fields (`w`, `h`, `d`, `c`) to the new values, setting `dims` to the appropriate rank, and recomputing `cstep` using `alignSize(..., 16) / elemsize`. The returned `Mat` shares the original data pointer, with reference counting (`addref`) ensuring the buffer remains valid until all views are released.

## The Four ncnn Mat reshape() Overloads

While the internal logic remains consistent, ncnn provides four distinct method signatures that differ only in the target tensor rank:

1. **`Mat reshape(int _w, Allocator* =0) const`** — Creates a **1‑D vector** view with width `_w`, flattening all dimensions into a single row.
2. **`Mat reshape(int _w, int _h, Allocator* =0) const`** — Creates a **2‑D image** matrix of shape `(w, h)`, interpreting the data as rows and columns.
3. **`Mat reshape(int _w, int _h, int _c, Allocator* =0) const`** — Creates a **3‑D tensor** with spatial dimensions `(w, h)` and `_c` channels.
4. **`Mat reshape(int _w, int _h, int _d, int _c, Allocator* =0) const`** — Creates a **4‑D cube** tensor of shape `(w, h, d, c)` for volumetric data or batched processing.

All overloads accept an optional `Allocator*` parameter used only when a memory copy is required due to non-contiguous layouts.

## When ncnn Mat Reshape Triggers Memory Copies

Zero-copy reshaping occurs only when the source tensor maintains a contiguous memory layout where each channel immediately follows the previous without padding. However, copies are automatically triggered in two specific scenarios:

- **Channel-aligned tensors**: When `cstep != w * h * d`, indicating that each channel is aligned to 16-byte boundaries for SIMD optimization.
- **Packed tensors**: When `elempack > 1` (multiple elements packed into a single register), the stride calculations no longer match a simple reshape view.

In these cases, ncnn prioritizes data correctness over performance, allocating new memory and copying channel-by-channel to create a properly contiguous buffer before returning the reshaped `Mat`.

## Practical Examples of ncnn Tensor Reshaping

### Flattening a 3‑D Feature Map to 1‑D

Convert a spatial feature map into a vector for fully-connected layer input without copying memory:

```cpp
ncnn::Mat feat = /* shape (w=64, h=64, c=32) */;
ncnn::Mat vec = feat.reshape(feat.total());   // 1‑D view, zero-copy

```

### Converting a Vector to a 2‑D Matrix

Reshape a flattened tensor back into spatial dimensions for convolutional processing:

```cpp
ncnn::Mat vec = /* shape (N) */;
int new_w = 128;
int new_h = N / 128;
ncnn::Mat img = vec.reshape(new_w, new_h);   // 2‑D view (128, new_h)

```

### Reshaping 4‑D Volumetric Data

Handle depth or batch dimensions by specifying all four parameters:

```cpp
ncnn::Mat blob = /* (w=224, h=224, d=1, c=3) */;
ncnn::Mat cube = blob.reshape(112, 112, 2, 3); // (112,112,2,3)
// Note: May copy if original cstep was aligned differently

```

### Explicit Contiguity for Guaranteed Zero-Copy

When working with tensors that might have padding, clone first to ensure contiguous layout:

```cpp
ncnn::Mat packed = blob.clone();                 // ensure contiguous
ncnn::Mat reshaped = packed.reshape(112, 112, 2, 3); // guaranteed zero-copy

```

## Key Source Files

| File | Description |
|------|-------------|
| **[`src/mat.h`](https://github.com/Tencent/ncnn/blob/main/src/mat.h)** | Declares the `Mat` class and all four `reshape` overloads (lines 1400‑1460), including inline dimension accessors. |
| **[`src/mat.cpp`](https://github.com/Tencent/ncnn/blob/main/src/mat.cpp)** | Contains the complete reshape implementation including size validation, non-contiguous handling, and fast-path view creation (lines 60‑120). |
| **[`src/allocator.h`](https://github.com/Tencent/ncnn/blob/main/src/allocator.h)** | Defines the `Allocator` interface used when reshape operations require new memory allocation for non-contiguous tensors. |

## Summary

- **ncnn Mat reshape** creates views rather than copies when the tensor layout is contiguous, sharing the underlying buffer via reference counting.
- Four overloads support reshaping to 1‑D, 2‑D, 3‑D, and 4‑D tensors, differing only in the target rank and dimension parameters.
- **Non-contiguous tensors** (where `cstep != w * h * d`) trigger automatic per-channel memory copies to maintain data integrity.
- The total element count must remain constant across reshape operations; mismatched sizes result in an empty `Mat` return.
- Source files [`src/mat.h`](https://github.com/Tencent/ncnn/blob/main/src/mat.h) and [`src/mat.cpp`](https://github.com/Tencent/ncnn/blob/main/src/mat.cpp) implement the complete logic, with line‑specific optimizations for alignment and SIMD packing.

## Frequently Asked Questions

### Does ncnn Mat reshape allocate new memory?

Only when the source tensor has a non-contiguous layout or uses channel padding (`cstep != w * h * d`). In these cases, ncnn allocates a new buffer and copies data channel-by-channel to ensure the reshaped view interprets memory correctly. For contiguous tensors, reshape returns a zero-copy view sharing the original data pointer.

### What are the differences between the four reshape overloads in ncnn?

The overloads differ exclusively in the target tensor rank and the number of dimension parameters they accept: one parameter for 1‑D vectors, two for 2‑D matrices, three for 3‑D channel tensors, and four for 4‑D volumetric data. All overloads share identical internal logic for validation and memory handling.

### How does ncnn handle reshaping packed or aligned tensors?

When `elempack > 1` or when channels are aligned to 16-byte boundaries (causing `cstep` to exceed `w * h * d`), ncnn detects the mismatch and performs a flattening copy operation. This copies each channel's raw data sequentially into a new contiguous buffer, preventing alignment bytes from being interpreted as tensor values.

### Can ncnn Mat reshape change the total number of elements?

No. The product of the source dimensions (`w * h * d * c * elempack`) must exactly equal the product of the target dimensions. If you attempt to reshape to a different total size, the function returns an empty `Mat` object, protecting against buffer overruns and data corruption.