Code size: OpenNN vs PyTorch
The OpenNN library has 64,351 lines of source code, 96% fewer than PyTorch’s 1,630,144. A small classification application takes 9 lines with OpenNN and 29 with PyTorch.
A smaller codebase is easier to read, review and maintain. Line counts measure size, not features: PyTorch offers a much wider range of models and tools.
Results
| Scope | OpenNN | PyTorch | Reduction |
|---|---|---|---|
| Library source lines | 64,351 | 1,630,144 | 96.05% |
| Application body lines | 9 | 29 | 68.97% |
Library source
We counted lines with cloc 1.98 in C++, C/C++ header, CUDA and Python files, excluding blank lines and comments.
- OpenNN: the
opennn/library folder at commit 84bd178e8, 254 files. - PyTorch: version 2.13.0 (
aten/src,c10,caffe2,torchandfunctorch), 6,416 files, excluding tests, tools, benchmarks, examples and third-party code.
Application code
Both programs read the breast cancer dataset, train a small classifier and report its binary-classification results.
OpenNN (C++)
#include <iostream>
#include "opennn/core/configuration.h"
#include "opennn/dataset/tabular_dataset.h"
#include "opennn/models/models.h"
#include "opennn/training/training.h"
#include "opennn/evaluation/evaluation.h"
using namespace opennn;
int main()
{
try
{
cout << "OpenNN. Breast Cancer Example." << endl;
Configuration::instance().set(Device::CPU, Type::FP32);
TabularDataset dataset("../data/breast_cancer/breast_cancer.csv", ";", true, false);
ClassificationNetwork network(dataset.get_input_shape(), {3}, dataset.get_target_shape());
Training training(&network, &dataset);
training.train();
Evaluation evaluation(&network, &dataset);
evaluation.print_binary_classification_tests();
cout << "Good bye!" << endl;
return 0;
}
catch(const exception& e)
{
cerr << e.what() << endl;
return 1;
}
}
PyTorch (Python)
import sys
import pandas as pd
import torch
frame = pd.read_csv(sys.argv[1], sep=";")
inputs = torch.tensor(frame.iloc[:, :-1].to_numpy(), dtype=torch.float32)
targets = torch.tensor(frame.iloc[:, -1:].to_numpy(), dtype=torch.float32)
split = int(0.8 * len(inputs))
permutation = torch.randperm(len(inputs))
train, test = permutation[:split], permutation[split:]
mean, deviation = inputs[train].mean(0), inputs[train].std(0).clamp(min=1e-8)
inputs = (inputs - mean) / deviation
network = torch.nn.Sequential(torch.nn.Linear(inputs.shape[1], 3),
torch.nn.Tanh(),
torch.nn.Linear(3, 1))
loss_function = torch.nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(network.parameters())
for _ in range(1000):
optimizer.zero_grad()
loss = loss_function(network(inputs[train]), targets[train])
loss.backward()
optimizer.step()
with torch.no_grad():
predictions = (network(inputs[test]) > 0).float()
actual = targets[test]
true_positive = int(((predictions == 1) & (actual == 1)).sum())
true_negative = int(((predictions == 0) & (actual == 0)).sum())
false_positive = int(((predictions == 1) & (actual == 0)).sum())
false_negative = int(((predictions == 0) & (actual == 1)).sum())
print(f"confusion matrix: {true_positive} {false_positive} {false_negative} {true_negative}")
print(f"accuracy: {(true_positive + true_negative) / len(actual):.4f}")
print(f"sensitivity: {true_positive / max(true_positive + false_negative, 1):.4f}")
print(f"specificity: {true_negative / max(true_negative + false_positive, 1):.4f}")
We counted the body of each application: the lines that do the work, print progress or report results. We excluded includes and imports, the namespace directive, the declaration of main, lines with only braces, the outer exception handling and the final return statements. The OpenNN body has seven task lines and two progress messages; the PyTorch body has 29 lines.
In the PyTorch version the caller writes the data split, the scaling, the training loop, the gradient step and the classification report. In OpenNN these are done by Training and Evaluation. Training defaults and report formats differ between the two programs, so the comparison describes these two examples rather than every application.
Source files at commit 5b4dac2cc: OpenNN example and PyTorch counterpart.
See also deployment size and prediction quality.