Implementation:Tencent Ncnn Npy Reader
| Knowledge Sources | |
|---|---|
| Domains | Data_IO, Quantization_Tools |
| Last Updated | 2026-02-09 19:00 GMT |
Overview
A header-only C++ library for reading and writing NumPy .npy and .npz array files, used by the quantization tools to load calibration data stored in NumPy format.
Description
npy.hpp is a third-party dependency (MIT-licensed, by Leon Merten Lohse) that provides complete support for the NumPy array file format. It lives in the npy namespace and defines core data structures and templated I/O functions.
The library defines several key types:
- dtype_t - describes the data type with byteorder (< for little-endian, > for big-endian, | for not applicable), kind (f for float, i for signed integer, u for unsigned integer, c for complex), and itemsize in bytes
- header_t - stores dtype, fortran_order flag, and shape as a vector of ndarray_len_t (unsigned long int)
- npy_data<Scalar> - templated struct holding the data vector, shape, and fortran_order flag
- npy_data_ptr<Scalar> - templated struct holding a const pointer to data, shape, and fortran_order flag (for zero-copy writing)
The library handles endianness detection at compile time using platform-specific macros and provides byte-order conversion when needed. The magic string (\x93NUMPY) and version number are validated during reading.
Templated I/O functions include:
- read_npy<Scalar>(filename) / read_npy<Scalar>(istream) - reads a .npy file into an npy_data struct
- write_npy<Scalar>(filename, data) / write_npy<Scalar>(ostream, data) - writes data to a .npy file
- Overloaded variants for npy_data_ptr that use pointer-based data for zero-copy output
- Legacy API with separate shape/data parameters for backward compatibility
Usage
This library is used by the ncnn2table calibration tool to accept NumPy .npy files as input calibration data alongside image files. It enables Python-trained quantization calibration datasets to be directly consumed by the C++ quantization toolchain.
Code Reference
Source Location
- Repository: Tencent_Ncnn
- File: tools/quantize/npy.hpp
- Lines: 1-600
Signature
namespace npy {
using ndarray_len_t = unsigned long int;
using shape_t = std::vector<ndarray_len_t>;
using version_t = std::pair<char, char>;
struct dtype_t {
char byteorder;
char kind;
unsigned int itemsize;
std::string str() const;
};
struct header_t {
dtype_t dtype;
bool fortran_order;
shape_t shape;
};
template <typename Scalar>
struct npy_data {
std::vector<Scalar> data;
shape_t shape;
bool fortran_order;
};
template <typename Scalar>
struct npy_data_ptr {
const Scalar* data_ptr;
shape_t shape;
bool fortran_order;
};
template <typename Scalar>
inline npy_data<Scalar> read_npy(const std::string& filename);
template <typename Scalar>
inline npy_data<Scalar> read_npy(std::istream& in);
template <typename Scalar>
inline void write_npy(const std::string& filename, const npy_data<Scalar>& data);
template <typename Scalar>
inline void write_npy(std::ostream& out, const npy_data<Scalar>& data);
} // namespace npy
Import
// Header-only library
#include "npy.hpp"
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| filename | std::string | Yes | Path to the .npy file to read |
| Scalar | template type | Yes | C++ scalar type (float, double, int, etc.) matching the .npy dtype |
Outputs
| Name | Type | Description |
|---|---|---|
| npy_data<Scalar> | struct | Contains data vector, shape vector, and fortran_order flag |
Usage Examples
Reading a NumPy File
#include "npy.hpp"
// Read a float array from a .npy file
npy::npy_data<float> d = npy::read_npy<float>("calibration_data.npy");
std::vector<float>& data = d.data;
npy::shape_t& shape = d.shape;
// shape[0] = number of samples, shape[1..] = dimensions
Writing a NumPy File
#include "npy.hpp"
npy::npy_data<float> d;
d.data = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
d.shape = {2, 3};
d.fortran_order = false;
npy::write_npy<float>("output.npy", d);