From baa631dd6635ed5c8ec2c6bb056f7237011fa722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Monta=C3=B1ana=20G=C3=B3mez?= Date: Wed, 18 Sep 2024 12:13:11 +0200 Subject: [PATCH] Add Cuda iniitialization in Classifier --- CMakeLists.txt | 11 ++++++++--- bayesnet/classifiers/Classifier.cc | 14 +++++++++++--- bayesnet/classifiers/Classifier.h | 1 + bayesnet/network/Node.cc | 2 +- sample/sample.cc | 22 +++++++++++++++------- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 784ed4e..f72a492 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,10 +51,15 @@ endif (CMAKE_BUILD_TYPE STREQUAL "Debug") if (CODE_COVERAGE) +get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) +message("ALL LANGUAGES: ${LANGUAGES}") +foreach(LANG ${LANGUAGES}) + message("${LANG} compiler is \"${CMAKE_${LANG}_COMPILER_ID}\"") +endforeach() enable_testing() - include(CodeCoverage) - MESSAGE("Code coverage enabled") - SET(GCC_COVERAGE_LINK_FLAGS " ${GCC_COVERAGE_LINK_FLAGS} -lgcov --coverage") + #include(CodeCoverage) + #MESSAGE("Code coverage enabled") + #SET(GCC_COVERAGE_LINK_FLAGS " ${GCC_COVERAGE_LINK_FLAGS} -lgcov --coverage") endif (CODE_COVERAGE) if (ENABLE_CLANG_TIDY) diff --git a/bayesnet/classifiers/Classifier.cc b/bayesnet/classifiers/Classifier.cc index 5262401..5b1d56b 100644 --- a/bayesnet/classifiers/Classifier.cc +++ b/bayesnet/classifiers/Classifier.cc @@ -9,7 +9,15 @@ #include "Classifier.h" namespace bayesnet { - Classifier::Classifier(Network model) : model(model), m(0), n(0), metrics(Metrics()), fitted(false) {} + Classifier::Classifier(Network model) : model(model), m(0), n(0), metrics(Metrics()), fitted(false), device(torch::kCPU) + { + if (torch::cuda::is_available()) { + device = torch::Device(torch::kCUDA); + std::cout << "CUDA is available! Using GPU." << std::endl; + } else { + std::cout << "CUDA is not available. Using CPU." << std::endl; + } + } const std::string CLASSIFIER_NOT_FITTED = "Classifier has not been fitted"; Classifier& Classifier::build(const std::vector& features, const std::string& className, std::map>& states, const torch::Tensor& weights, const Smoothing_t smoothing) { @@ -31,7 +39,7 @@ namespace bayesnet { { try { auto yresized = torch::transpose(ytmp.view({ ytmp.size(0), 1 }), 0, 1); - dataset = torch::cat({ dataset, yresized }, 0); + dataset = torch::cat({ dataset, yresized }, 0).to(device); } catch (const std::exception& e) { std::stringstream oss; @@ -50,7 +58,7 @@ namespace bayesnet { { dataset = X; buildDataset(y); - const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble); + const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble).to(device); return build(features, className, states, weights, smoothing); } // X is nxm where n is the number of features and m the number of samples diff --git a/bayesnet/classifiers/Classifier.h b/bayesnet/classifiers/Classifier.h index 4d3ea83..cbc74cf 100644 --- a/bayesnet/classifiers/Classifier.h +++ b/bayesnet/classifiers/Classifier.h @@ -38,6 +38,7 @@ namespace bayesnet { std::string dump_cpt() const override; void setHyperparameters(const nlohmann::json& hyperparameters) override; //For classifiers that don't have hyperparameters protected: + torch::Device device; bool fitted; unsigned int m, n; // m: number of samples, n: number of features Network model; diff --git a/bayesnet/network/Node.cc b/bayesnet/network/Node.cc index b62e275..b268150 100644 --- a/bayesnet/network/Node.cc +++ b/bayesnet/network/Node.cc @@ -97,7 +97,7 @@ namespace bayesnet { dimensions.push_back(numStates); transform(parents.begin(), parents.end(), back_inserter(dimensions), [](const auto& parent) { return parent->getNumStates(); }); // Create a tensor of zeros with the dimensions of the CPT - cpTable = torch::zeros(dimensions, torch::kDouble) + smoothing; + cpTable = torch::zeros(dimensions, torch::kDouble).to(device) + smoothing; // Fill table with counts auto pos = find(features.begin(), features.end(), name); if (pos == features.end()) { diff --git a/sample/sample.cc b/sample/sample.cc index 478ff85..d528d83 100644 --- a/sample/sample.cc +++ b/sample/sample.cc @@ -7,6 +7,7 @@ #include #include #include +#include std::vector discretizeDataset(std::vector& X, mdlp::labels_t& y) { @@ -19,7 +20,8 @@ std::vector discretizeDataset(std::vector& X, m } return Xd; } -tuple, std::string, map>> loadDataset(const std::string& name, bool class_last) + +tuple, std::string, map>> loadDataset(const std::string& name, bool class_last, torch::Device device) { auto handler = ArffFiles(); handler.load(name, class_last); @@ -34,16 +36,16 @@ tuple, std::string, map>(); auto Xr = discretizeDataset(X, y); - Xd = torch::zeros({ static_cast(Xr.size()), static_cast(Xr[0].size()) }, torch::kInt32); + Xd = torch::zeros({ static_cast(Xr.size()), static_cast(Xr[0].size()) }, torch::kInt32).to(device); for (int i = 0; i < features.size(); ++i) { states[features[i]] = std::vector(*max_element(Xr[i].begin(), Xr[i].end()) + 1); auto item = states.at(features[i]); iota(begin(item), end(item), 0); - Xd.index_put_({ i, "..." }, torch::tensor(Xr[i], torch::kInt32)); + Xd.index_put_({ i, "..." }, torch::tensor(Xr[i], torch::kInt32).to(device)); } states[className] = std::vector(*max_element(y.begin(), y.end()) + 1); iota(begin(states.at(className)), end(states.at(className)), 0); - return { Xd, torch::tensor(y, torch::kInt32), features, className, states }; + return { Xd, torch::tensor(y, torch::kInt32).to(device), features, className, states }; } int main(int argc, char* argv[]) @@ -53,16 +55,22 @@ int main(int argc, char* argv[]) return 1; } std::string file_name = argv[1]; + torch::Device device(torch::kCPU); + if (torch::cuda::is_available()) { + device = torch::Device(torch::kCUDA); + std::cout << "CUDA is available! Using GPU." << std::endl; + } else { + std::cout << "CUDA is not available. Using CPU." << std::endl; + } torch::Tensor X, y; std::vector features; std::string className; map> states; auto clf = bayesnet::BoostAODE(false); // false for not using voting in predict std::cout << "Library version: " << clf.getVersion() << std::endl; - tie(X, y, features, className, states) = loadDataset(file_name, true); + tie(X, y, features, className, states) = loadDataset(file_name, true, device); clf.fit(X, y, features, className, states, bayesnet::Smoothing_t::LAPLACE); auto score = clf.score(X, y); std::cout << "File: " << file_name << " Model: BoostAODE score: " << score << std::endl; return 0; -} - +} \ No newline at end of file