Skip to content

‹ Back to Benchmarks

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

Lines of code
Lower is better
Blank lines and comments excluded
Library source · 96% fewer
Application body · 69% fewer
The two rows have different scopes and are counted separately.
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, torch and functorch), 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.