Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

PROJECT(singa)

IF(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
SET(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
ENDIF()

LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Thirdparty)

#include(GetGitRevisionDescription)
Expand Down Expand Up @@ -47,10 +51,10 @@ message(STATUS "SINGA Version ${SINGA_VERSION}")

# Flags
IF(UNIX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -O2 -fPIC -Wall -pthread")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wall -pthread")
ENDIF()
IF(APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -g -O2 -fPIC -Wall -pthread")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -fPIC -Wall -pthread")
SET(CMAKE_MACOSX_RPATH 1)
ENDIF()

Expand All @@ -61,7 +65,7 @@ IF(WIN32)
#MESSAGE(STATUS "Using msvc compiler ${CMAKE_CXX_FLAGS}")
ENDIF()
ENDIF()
IF(CMAKE_BUILD_TYPE=Debug)
IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(NVCC_FLAG "${NVCC_FLAG} -g -G ")
ENDIF()
#message(STATUS "${CMAKE_CXX_FLAGS}")
Expand Down
1 change: 1 addition & 0 deletions cmake/Dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ IF(USE_MODULES)
#ENDIF()
ELSE()
FIND_PACKAGE( Protobuf 3.0 REQUIRED )
INCLUDE_DIRECTORIES(${Protobuf_INCLUDE_DIRS})
#MESSAGE(STATUS "proto libs " ${PROTOBUF_LIBRARY})
LIST(APPEND SINGA_LINKER_LIBS ${PROTOBUF_LIBRARY})
#IF(USE_CBLAS)
Expand Down
104 changes: 104 additions & 0 deletions examples/neurostore/model_compression.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@

/**
* @file model_compression.cpp
* Demonstrate model compression using NeurStore
*/

// make sure you have local neurostore runtime enviroment
#include "neurstore/neurstore.h"

#include <filesystem>
#include <chrono>
#include <iostream>

namespace fs = std::filesystem;
using namespace std::chrono;

std::vector<uint8_t> read_file(const std::string &path) {
std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file) {
throw std::runtime_error("Failed to open file: " + path);
}
std::streamsize size = file.tellg();
if (size <= 0) {
throw std::runtime_error("File is empty or unreadable: " + path);
}
file.seekg(0, std::ios::beg);
std::vector<uint8_t> buffer(size);
if (!file.read(reinterpret_cast<char *>(buffer.data()), size)) {
throw std::runtime_error("Failed to read file contents: " + path);
}
return buffer;
}

int main(int argc, char **argv) {
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " <model_folder> <tolerance> <parallelism>" << std::endl;
return 1;
}
const std::string model_folder = argv[1];
const double tolerance = std::stod(argv[2]);
const int parallelism = std::stoi(argv[3]);

omp_set_num_threads(parallelism);

std::vector<std::string> model_names;

for (const auto& entry : fs::directory_iterator(model_folder)) {
if (entry.is_regular_file()) {
const std::string filename = entry.path().filename().string();
if (entry.path().extension() == ".onnx") {
model_names.push_back(filename.substr(0, filename.size() - 5));
}
}
}

std::string outputFolder = "./neurstore_compression_example";
fs::create_directories(outputFolder);

const NeurStore neurstore(outputFolder, std::make_shared<IndexCacheManager>(outputFolder));
auto start = high_resolution_clock::now();
bool success = false;
try {
success = neurstore.saveModels(model_names, tolerance, model_folder);
} catch (const std::exception &e) {
std::cerr << "Exception during compression: " << e.what() << std::endl;
return 1;
}
if (!success) {
std::cerr << "Compression failed." << std::endl;
return 1;
}
const auto end = high_resolution_clock::now();
const double elapsed = duration_cast<duration<double>>(end - start).count();

double compressed_size = 0.0; // MB
for (const auto &file : std::filesystem::recursive_directory_iterator(outputFolder)) {
if (file.is_regular_file()) {
compressed_size += static_cast<double>(file.file_size()) / (1024 * 1024);
}
}

double original_size = 0.0; // MB
for (const auto &name: model_names) {
std::string path = fs::path(model_folder) / (name + ".onnx");
try {
auto raw = read_file(path);
original_size += static_cast<double>(raw.size()) / (1024 * 1024);
} catch (...) {
std::cerr << "Failed to read: " << path << std::endl;
}
}

std::cout << "================ Compression Summary ================" << std::endl;
std::cout << "Compressing models from folder: " << model_folder << std::endl;
std::cout << "Tolerance: " << tolerance << ", Parallelism: " << parallelism << std::endl;
std::cout << "-----------------------------------------------------" << std::endl;
std::cout << "Total models compressed: " << model_names.size() << std::endl;
std::cout << "Total time: " << elapsed << " sec" << std::endl;
std::cout << "Total original size: " << original_size << " MB" << std::endl;
std::cout << "Total compressed size: " << compressed_size << " MB" << std::endl;
std::cout << "Compression ratio: " << (original_size / compressed_size) << std::endl;
std::cout << "=====================================================" << std::endl;
return 0;
}
105 changes: 105 additions & 0 deletions examples/neurostore/model_compression_and_decompression_from_list.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "neurstore/neurstore.h"

#include <filesystem>
#include <fstream>
#include <iostream>
#include <omp.h>

namespace fs = std::filesystem;

std::vector<std::string> readModelList(const std::string &path) {
std::ifstream file(path);
if (!file.is_open())
throw std::runtime_error("Failed to open model list file: " + path);

std::vector<std::string> modelPaths;
std::string line;
while (std::getline(file, line))
if (!line.empty()) modelPaths.emplace_back(std::move(line));
return modelPaths;
}

std::vector<char> readFile(const std::string &path) {
std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.is_open())
throw std::runtime_error("Failed to open file: " + path);

std::streamsize size = file.tellg();
if (size <= 0)
throw std::runtime_error("Empty or invalid file: " + path);

std::vector<char> buffer(static_cast<size_t>(size));
file.seekg(0, std::ios::beg);
if (!file.read(buffer.data(), size))
throw std::runtime_error("Failed to read file: " + path);
return buffer;
}

int main(int argc, char **argv) {
if (argc != 6) {
std::cerr << "Usage: " << argv[0]
<< " <model_list.txt> <store_dir> <tolerance> <parallelism> <load_model_dir>\n";
return 1;
}

const std::string modelListPath = argv[1];
std::string storeDir = argv[2];
const double tolerance = std::stod(argv[3]);
const int parallelism = std::stoi(argv[4]);
const std::string loadModelDir = argv[5];

omp_set_num_threads(parallelism);
fs::create_directories(storeDir);
fs::create_directories(loadModelDir);

const auto modelPaths = readModelList(modelListPath);
auto cacheManager = std::make_shared<IndexCacheManager>(storeDir);
NeurStore neurstore(storeDir, cacheManager);

try {
if (!neurstore.saveModelsFromPaths(modelPaths, tolerance)) {
std::cerr << "Failed to save models to NeurStore.\n";
return 1;
}
cacheManager->clearCache();
} catch (const std::exception &e) {
std::cerr << "Compression exception: " << e.what() << '\n';
return 1;
}

for (const auto &modelPath: modelPaths) {
fs::path p(modelPath);
const std::string modelName = p.stem().string();

try {
auto modelProto = neurstore.loadModel(modelName);
std::string buffer;
modelProto->SerializeToString(&buffer);

fs::path outPath = fs::path(loadModelDir) / (modelName + ".onnx");
std::ofstream fout(outPath, std::ios::binary);
fout.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
std::cout << "[INFO] Loaded & dumped model: " << modelName << " -> "
<< outPath << '\n';
} catch (const std::exception &e) {
std::cerr << "[WARN] Failed to load/dump model " << modelName
<< ": " << e.what() << '\n';
}
}

double totalOriginalSize = 0.0, totalCompressedSize = 0.0;
for (const auto &mp: modelPaths)
totalOriginalSize += static_cast<double>(readFile(mp).size()) / (1024 * 1024);

for (const auto &entry: fs::directory_iterator(storeDir))
if (entry.is_regular_file())
totalCompressedSize += static_cast<double>(entry.file_size()) / (1024 * 1024);

std::cout << "\n================ Overall Summary (NeurStore) ================\n";
std::cout << "Total models processed : " << modelPaths.size() << '\n';
std::cout << "Compression ratio : " << (totalOriginalSize / totalCompressedSize) << '\n';
std::cout << "Total original size : " << totalOriginalSize << " MB\n";
std::cout << "Total compressed size : " << totalCompressedSize << " MB\n";
std::cout << "=============================================================\n";
return 0;
}
Loading