CuNet is a deep learning framework built entirely from scratch in C++17 and raw CUDA. It implements tensors, convolutions, backpropagation, and Adam optimization natively on the GPU without relying on cuDNN, PyTorch, TensorFlow, or any other external machine-learning libraries.
By building these components from the ground up, CuNet provides a transparent look into the mathematics and memory management behind modern deep learning.
CuNet is primarily an educational and engineering project focused on understanding and implementing deep learning systems from first principles.
The framework emphasizes:
- Raw CUDA implementations
- Transparent backpropagation
- Minimal dependencies
- GPU-native tensor operations
- Readable architecture for learning and experimentation
It is not currently intended to compete with production frameworks such as PyTorch or TensorFlow.
CuNet supports a modular Sequential API, similar to Keras or PyTorch, making it easy to stack layers and define models.
Core Components:
- Core: Custom GPU-backed
Tensorclass with automatic memory management and reshape capabilities. - Layers:
Conv2D,Dense,MaxPool2D,Flatten,Dropout. - Activations:
ReLU. - Loss Function:
CrossEntropy. - Optimizer:
Adam.
The framework includes a fully functioning example (examples/mnist_trainer.cpp) that trains a VGG-style CNN on the standard MNIST dataset.
Training Configuration:
- Dataset: MNIST (60,000 Train / 10,000 Test)
- Model Architecture:
Conv2D(16) -> ReLU -> MaxPool2D -> Conv2D(32) -> ReLU -> MaxPool2D -> Flatten -> Dropout(0.3) -> Dense(128) -> ReLU -> Dense(10) - Epochs: 10
- Batch Size: 64
- Learning Rate: 0.001
Results (Hardware: NVIDIA RTX 3060 Laptop):
- Test Accuracy: ~99.15%
- Training Time: ~46.7 seconds
Requirements:
- CMake 3.17 or higher
- NVIDIA CUDA Toolkit
- A C++17 compatible compiler (e.g., MSVC on Windows, GCC on Linux)
Building and Running (Windows): The project includes utility PowerShell scripts for easy compilation and execution.
-
Clone the repository and ensure your MNIST dataset is extracted to
data\mnist-dataset\. -
Build and run the main MNIST training example:
./build-and-run.ps1
-
To build and run the unit tests (verifying gradients, loss functions, and layer shapes):
./build-and-run-tests.ps1
Building a model is straightforward using the Sequential class:
#include "models/Sequential.hpp"
#include "layers/Conv2D.hpp"
#include "layers/ReLU.hpp"
#include "layers/MaxPool2D.hpp"
#include "layers/Flatten.hpp"
#include "layers/Dropout.hpp"
#include "layers/Dense.hpp"
#include "loss/CrossEntropy.hpp"
int main() {
// 1. Initialize Model
Sequential model(std::make_unique<CrossEntropy>());
// 2. Build Architecture (Input: [Batch, 28, 28, 1])
model.addLayer(std::make_unique<Conv2D>(1, 16, 3, 1, 1));
model.addLayer(std::make_unique<ReLU>());
model.addLayer(std::make_unique<MaxPool2D>(2, 2));
model.addLayer(std::make_unique<Conv2D>(16, 32, 3, 1, 1));
model.addLayer(std::make_unique<ReLU>());
model.addLayer(std::make_unique<MaxPool2D>(2, 2));
model.addLayer(std::make_unique<Flatten>());
model.addLayer(std::make_unique<Dropout>(0.3f));
model.addLayer(std::make_unique<Dense>(1568, 128));
model.addLayer(std::make_unique<ReLU>());
model.addLayer(std::make_unique<Dense>(128, 10));
// 3. Train
model.setTrainingMode(true);
// ... load data into Tensors X and Y ...
for(int epoch = 0; epoch < epochs; epoch++){
for(auto& batch : train_batches){
Tensor logits = model.forward(batch.X);
float loss = model.computeLossAndBackward(logits, batch.Y);
model.updateWeights(0.001f); // Adam optimizer step
}
}
// 4. Evaluate
model.setTrainingMode(false); // Disable dropout for inference
// ... run test evaluation ...
return 0;
}CuNet is an actively evolving project. Current areas of focus and planned features include:
- Model Serialization (Save/Load): Save trained models to disk and reload them for inference without retraining.
- Data Augmentation Pipeline: Adding native CPU/GPU functions to randomly shift, rotate, and scale images during the training loop to improve model generalization.
- Batch Normalization: Implementing a
BatchNorm2Dlayer to stabilize gradients and allow for higher learning rates. - Expanded Layer Support: Introducing padding options, Average Pooling, and recurrent architectures.
- Kernel Optimization: Optimizing existing CUDA kernels to maximize hardware utilization and reduce training times.