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

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 (lines 60‑120) with declarations in 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:

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:

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:

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:

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:

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 Declares the Mat class and all four reshape overloads (lines 1400‑1460), including inline dimension accessors.
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 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 and 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →