Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature python interface #53

Merged
merged 10 commits into from
Sep 19, 2024
30 changes: 30 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ set(CMAKE_CXX_STANDARD 17)

project(nuTens)

# Changes default install path to be a subdirectory of the build dir.
# Can set build dir at configure time with -DCMAKE_INSTALL_PREFIX=/install/path
if(CMAKE_INSTALL_PREFIX STREQUAL "" OR CMAKE_INSTALL_PREFIX STREQUAL
"/usr/local")
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}")
elseif(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}")
endif()


# Need to add some special compile flags to check the code test coverage
OPTION(NT_TEST_COVERAGE "produce code coverage reports when running tests" OFF)
IF(NT_TEST_COVERAGE)
Expand Down Expand Up @@ -46,6 +56,19 @@ ELSE()
message("Won't benchmark")
ENDIF()

# If user wants to enable python interface we need to include pybind
OPTION(NT_ENABLE_PYTHON "enable python interface" OFF)
IF(NT_ENABLE_PYTHON)
message("Enabling python")
CPMAddPackage(
GITHUB_REPOSITORY "pybind/pybind11"
VERSION 2.13.5
)

ELSE()
message("Won't enable python interface")
ENDIF()


## check build times
## have this optional as it's not supported on all CMake platforms
Expand All @@ -66,6 +89,13 @@ IF(NT_ENABLE_BENCHMARKING)
add_subdirectory(benchmarks)
ENDIF()

IF(NT_ENABLE_PYTHON)
set_property( TARGET tensor PROPERTY POSITION_INDEPENDENT_CODE ON )
set_property( TARGET propagator PROPERTY POSITION_INDEPENDENT_CODE ON )
set_property( TARGET spdlog PROPERTY POSITION_INDEPENDENT_CODE ON )
set_property( TARGET logging PROPERTY POSITION_INDEPENDENT_CODE ON )
add_subdirectory(python)
ENDIF()

# Print out a handy message to more easily see the config options
message( STATUS "The following variables have been used to configure the build: " )
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ nuTens uses [Googles benchmark library](https://github.com/google/benchmark) to
- [x] Add suite of benchmarking tests
- [x] Integrate benchmarks into CI ( maybe use [hyperfine](https://github.com/sharkdp/hyperfine) and [bencher](https://bencher.dev/) for this? )
- [ ] Add proper unit tests
- [ ] Expand CI to include more platforms
- [x] Expand CI to include more platforms
- [ ] Add support for modules (see [PyTorch doc](https://pytorch.org/cppdocs/api/classtorch_1_1nn_1_1_module.html))
- [ ] Propagation in variable matter density
- [ ] Add support for Tensorflow backend
- [ ] Add python interface
- [x] Add python interface

1 change: 1 addition & 0 deletions nuTens/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
add_library(logging logging.hpp)
target_link_libraries(logging spdlog::spdlog)
set_target_properties(logging PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(logging PUBLIC "${SPDLOG_INCLUDE_DIRS}")

set( NT_LOG_LEVEL "INFO" CACHE STRING "the level of detail to log to the console" )

Expand Down
4 changes: 2 additions & 2 deletions nuTens/propagator/const-density-solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ void ConstDensityMatterSolver::calculateEigenvalues(const Tensor &energies, Tens
for (int j = 0; j < nGenerations; j++)
{
hamiltonian.setValue({"...", i, j},
Tensor::div(diagMassMatrix.getValue({i, j}), energies.getValue({"...", 0})) -
electronOuter.getValue({i, j}));
Tensor::div(diagMassMatrix.getValues({i, j}), energies.getValues({"...", 0})) -
electronOuter.getValues({i, j}));
}
}

Expand Down
7 changes: 4 additions & 3 deletions nuTens/propagator/const-density-solver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@

// construct the outer product of the electron neutrino row of the PMNS
// matrix used to construct the hamiltonian
electronOuter = Tensor::scale(Tensor::outer(PMNS.getValue({0, 0, "..."}), PMNS.getValue({0, 0, "..."}).conj()),
Constants::Groot2 * density);
electronOuter =
Tensor::scale(Tensor::outer(PMNS.getValues({0, 0, "..."}), PMNS.getValues({0, 0, "..."}).conj()),
Constants::Groot2 * density);
};

/// @brief Set new mass eigenvalues for this solver
Expand All @@ -64,7 +65,7 @@

masses = newMasses;

Tensor m = masses.getValue({0, "..."});
Tensor m = masses.getValues({0, "..."});
Tensor diag = Tensor::scale(Tensor::mul(m, m), 0.5);

// construct the diagonal mass^2 matrix used in the hamiltonian
Expand All @@ -79,7 +80,7 @@
/// shape should look like {Nbatches, 1, 1}.
/// @param[out] eigenvectors The returned eigenvectors
/// @param[out] eigenvalues The corresponding eigenvalues
void calculateEigenvalues(const Tensor &energies, Tensor &eigenvectors, Tensor &eigenvalues);

Check warning on line 83 in nuTens/propagator/const-density-solver.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter

nuTens/propagator/const-density-solver.hpp:83:10 [clang-diagnostic-inconsistent-missing-override]

'calculateEigenvalues' overrides a member function but is not marked 'override'

private:
Tensor PMNS;
Expand Down
2 changes: 1 addition & 1 deletion nuTens/propagator/propagator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Tensor Propagator::_calculateProbs(const Tensor &energies, const Tensor &massesS
{
for (int j = 0; j < _nGenerations; j++)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy diagnostic

nuTens/propagator/propagator.cpp:45:23: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                      ^

clang-tidy diagnostic

nuTens/propagator/propagator.cpp:45:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                                                                        ^

clang-tidy diagnostic

nuTens/propagator/propagator.cpp:45:94: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                                                                                             ^

clang-tidy diagnostic

nuTens/propagator/propagator.hpp:42:35: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                  ^

clang-tidy diagnostic

nuTens/propagator/propagator.hpp:42:76: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                                                           ^

clang-tidy diagnostic

nuTens/propagator/propagator.hpp:42:97: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                                                                                ^

clang-tidy diagnostic

nuTens/propagator/propagator.hpp:45:23: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                      ^

clang-tidy diagnostic

nuTens/propagator/propagator.hpp:45:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                                                                        ^

clang-tidy diagnostic

nuTens/propagator/propagator.hpp:45:94: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                                                                                             ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:30:14: error: [clang-diagnostic-error]

use of undeclared identifier 'std'

const static std::map<scalarType, c10::ScalarType> scalarTypeMap = {{kFloat, torch::kFloat},
             ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:30:35: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<scalarType, c10::ScalarType> scalarTypeMap = {{kFloat, torch::kFloat},
                                  ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:30:78: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<scalarType, c10::ScalarType> scalarTypeMap = {{kFloat, torch::kFloat},
                                                                             ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:31:79: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                    {kDouble, torch::kDouble},
                                                                              ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:32:85: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                    {kComplexFloat, torch::kComplexFloat},
                                                                                    ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:33:86: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                    {kComplexDouble, torch::kComplexDouble}};
                                                                                     ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:36:14: error: [clang-diagnostic-error]

use of undeclared identifier 'std'

const static std::map<c10::ScalarType, scalarType> invScalarTypeMap = {{torch::kFloat, kFloat},
             ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:36:23: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<c10::ScalarType, scalarType> invScalarTypeMap = {{torch::kFloat, kFloat},
                      ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:36:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::ScalarType, scalarType> invScalarTypeMap = {{torch::kFloat, kFloat},
                                                                        ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:37:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                       {torch::kDouble, kDouble},
                                                                        ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:38:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                       {torch::kComplexFloat, kComplexFloat},
                                                                        ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:39:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                       {torch::kComplexDouble, kComplexDouble}};
                                                                        ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:42:14: error: [clang-diagnostic-error]

use of undeclared identifier 'std'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
             ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:42:35: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                  ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:42:76: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                                                           ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:42:97: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                                                                                ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:45:14: error: [clang-diagnostic-error]

use of undeclared identifier 'std'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
             ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:45:23: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                      ^

clang-tidy diagnostic

nuTens/tensors/dtypes.hpp:45:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                                                                        ^

clang-tidy diagnostic

nuTens/tensors/tensor.hpp:42:35: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                  ^

clang-tidy diagnostic

nuTens/tensors/tensor.hpp:42:76: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                                                           ^

clang-tidy diagnostic

nuTens/tensors/tensor.hpp:42:97: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                                                                                ^

clang-tidy diagnostic

nuTens/tensors/tensor.hpp:45:23: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                      ^

clang-tidy diagnostic

nuTens/tensors/tensor.hpp:45:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                                                                        ^

clang-tidy diagnostic

nuTens/tensors/tensor.hpp:45:94: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                                                                                             ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:30:35: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<scalarType, c10::ScalarType> scalarTypeMap = {{kFloat, torch::kFloat},
                                  ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:30:78: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<scalarType, c10::ScalarType> scalarTypeMap = {{kFloat, torch::kFloat},
                                                                             ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:31:79: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                    {kDouble, torch::kDouble},
                                                                              ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:32:85: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                    {kComplexFloat, torch::kComplexFloat},
                                                                                    ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:33:86: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                    {kComplexDouble, torch::kComplexDouble}};
                                                                                     ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:38:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                       {torch::kComplexFloat, kComplexFloat},
                                                                        ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:39:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                       {torch::kComplexDouble, kComplexDouble}};
                                                                        ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:42:35: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                  ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:42:76: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                                                           ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:42:97: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};
                                                                                                ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:45:23: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                      ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:45:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                                                                        ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:45:94: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
                                                                                             ^

clang-tidy diagnostic

python/pyNuTens.cpp:22:1: warning: [cppcoreguidelines-avoid-non-const-global-variables]

variable 'pybind11_module_def_pyNuTens' is non-const and globally accessible, consider making it const

PYBIND11_MODULE(pyNuTens, m)
^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:392:44: note: expanded from macro 'PYBIND11_MODULE'
    static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name)            \
                                           ^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:312:40: note: expanded from macro 'PYBIND11_CONCAT'
#define PYBIND11_CONCAT(first, second) first##second
                                       ^
note: expanded from here

clang-tidy diagnostic

python/pyNuTens.cpp:22:1: warning: [cppcoreguidelines-pro-bounds-pointer-arithmetic]

do not use pointer arithmetic

PYBIND11_MODULE(pyNuTens, m)
^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:397:9: note: expanded from macro 'PYBIND11_MODULE'
        PYBIND11_CHECK_PYTHON_VERSION                                                             \
        ^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:322:17: note: expanded from macro 'PYBIND11_CHECK_PYTHON_VERSION'
            || (runtime_ver[len] >= '0' && runtime_ver[len] <= '9')) {                            \
                ^

clang-tidy diagnostic

tests/tensor-basic.cpp:31:79: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                    {kDouble, torch::kDouble},
                                                                              ^

clang-tidy diagnostic

tests/tensor-basic.cpp:32:85: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                    {kComplexFloat, torch::kComplexFloat},
                                                                                    ^

clang-tidy diagnostic

tests/tensor-basic.cpp:33:86: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

                                                                    {kComplexDouble, torch::kComplexDouble}};
                                                                                     ^

clang-tidy diagnostic

tests/tensor-basic.cpp:36:14: error: [clang-diagnostic-error]

use of undeclared identifier 'std'

const static std::map<c10::ScalarType, scalarType> invScalarTypeMap = {{torch::kFloat, kFloat},
             ^

clang-tidy diagnostic

tests/tensor-basic.cpp:36:23: error: [clang-diagnostic-error]

use of undeclared identifier 'c10'

const static std::map<c10::ScalarType, scalarType> invScalarTypeMap = {{torch::kFloat, kFloat},
                      ^

clang-tidy diagnostic

tests/tensor-basic.cpp:36:73: error: [clang-diagnostic-error]

use of undeclared identifier 'torch'

const static std::map<c10::ScalarType, scalarType> invScalarTypeMap = {{torch::kFloat, kFloat},
                                                                        ^

{
weightMatrix.setValue({"...", i, j}, weightVector.getValue({"...", j}));
weightMatrix.setValue({"...", i, j}, weightVector.getValues({"...", j}));
}
}
weightMatrix.requiresGrad(true);
Expand Down
4 changes: 2 additions & 2 deletions nuTens/propagator/propagator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Propagator

/// @brief Set a matter solver to use to deal with matter effects
/// @param newSolver A derivative of BaseMatterSolver
inline void setMatterSolver(std::unique_ptr<BaseMatterSolver> &newSolver)
inline void setMatterSolver(std::shared_ptr<BaseMatterSolver> &newSolver)
{
NT_PROFILE();
_matterSolver = std::move(newSolver);
Expand Down Expand Up @@ -113,5 +113,5 @@ class Propagator
int _nGenerations;
float _baseline;

std::unique_ptr<BaseMatterSolver> _matterSolver;
std::shared_ptr<BaseMatterSolver> _matterSolver;
};
2 changes: 2 additions & 0 deletions nuTens/tensors/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ IF(NT_USE_PCH)
target_link_libraries(tensor PUBLIC nuTens-pch)

ELSE()
target_link_libraries(tensor PUBLIC logging)

IF(TORCH_FOUND)

target_link_libraries(tensor PUBLIC "${TORCH_LIBRARIES}")
Expand Down
23 changes: 23 additions & 0 deletions nuTens/tensors/dtypes.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#pragma once

#if USE_PYTORCH
#include <torch/torch.h>
#endif

/*!
* @file dtypes.hpp
* @brief Defines various datatypes used in the project
Expand All @@ -25,4 +29,23 @@ enum deviceType
kGPU
};

#if USE_PYTORCH
/// map between the data types used in nuTens and those used by pytorch
const static std::map<scalarType, c10::ScalarType> scalarTypeMap = {{kFloat, torch::kFloat},
{kDouble, torch::kDouble},
{kComplexFloat, torch::kComplexFloat},
{kComplexDouble, torch::kComplexDouble}};

/// inverse map between the data types used in nuTens and those used by pytorch
const static std::map<c10::ScalarType, scalarType> invScalarTypeMap = {{torch::kFloat, kFloat},
{torch::kDouble, kDouble},
{torch::kComplexFloat, kComplexFloat},
{torch::kComplexDouble, kComplexDouble}};

// map between the device types used in nuTens and those used by pytorch
const static std::map<deviceType, c10::DeviceType> deviceTypeMap = {{kCPU, torch::kCPU}, {kGPU, torch::kCUDA}};

// inverse map between the device types used in nuTens and those used by pytorch
const static std::map<c10::DeviceType, deviceType> invDeviceTypeMap = {{torch::kCPU, kCPU}, {torch::kCUDA, kGPU}};
#endif
} // namespace NTdtypes
117 changes: 101 additions & 16 deletions nuTens/tensors/tensor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <iostream>
#include <map>
#include <nuTens/instrumentation.hpp>
#include <nuTens/logging.hpp>
#include <nuTens/tensors/dtypes.hpp>
#include <variant>
#include <vector>
Expand Down Expand Up @@ -42,14 +43,19 @@
*/

public:
/// Holds the possible "index" types, this allows us to pass integers OR strings as index values which allows us to
/// do some basic slicing of tensors similar to python
using indexType = std::variant<int, std::string>;

/// Container that holds all allowed types that can be returned by a tensor
using variantType = std::variant<int, float, double, std::complex<float>, std::complex<double>>;

/// @name Constructors
/// Use these methods to construct tensors
/// @{

/// @brief Default constructor with no initialisation
Tensor(){};

Check warning on line 58 in nuTens/tensors/tensor.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter

nuTens/tensors/tensor.hpp:58:5 [cppcoreguidelines-pro-type-member-init]

constructor does not initialize these fields: _dType, _device

Check warning on line 58 in nuTens/tensors/tensor.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter

nuTens/tensors/tensor.hpp:58:5 [modernize-use-equals-default]

use '= default' to define a trivial default constructor

/// @brief Construct a 1-d array with specified values
/// @arg values The values to include in the tensor
Expand Down Expand Up @@ -233,13 +239,37 @@
/// @brief Get elementwise phases of a complex tensor
[[nodiscard]] Tensor angle() const;

/// @brief Get the result of summing this tensor over some dimension
/// @brief Get the cumulative sum over some dimension
/// @param dim The dimension to sum over
[[nodiscard]] Tensor cumsum(int dim) const;

/// @brief Get the result of summing this tensor over all dimensions
[[nodiscard]] Tensor sum() const;

/// @brief Get the result of summing this tensor over all dimensions
/// @param dims The dimensions to sum over
[[nodiscard]] Tensor sum(const std::vector<long int> &dims) const;

/// @brief Get the cumulative sum over some dimension
/// @param dim The dimension to sum over
static inline Tensor cumsum(const Tensor &t, int dim)
{
return t.cumsum(dim);
}

/// @brief Get the result of summing this tensor over all dimensions
static inline Tensor sum(const Tensor &t)
{
return t.sum();
}

/// @brief Get the result of summing this tensor over all dimensions
/// @param dims The dimensions to sum over
static inline Tensor sum(const Tensor &t, const std::vector<long int> &dims)
{
return t.sum(dims);
}

/// @name Gradients
/// @{

Expand Down Expand Up @@ -280,18 +310,24 @@
/// @arg indices The indices of the value to set
/// @arg value The value to set it to
void setValue(const Tensor &indices, const Tensor &value);
void setValue(const std::vector<std::variant<int, std::string>> &indices, const Tensor &value);
void setValue(const std::vector<indexType> &indices, const Tensor &value);
void setValue(const std::vector<int> &indices, float value);
void setValue(const std::vector<int> &indices, std::complex<float> value);

/// @brief Get the value at a certain entry in the tensor
/// @param indices The index of the entry to get
[[nodiscard]] Tensor getValue(const std::vector<std::variant<int, std::string>> &indices) const;
[[nodiscard]] Tensor getValues(const std::vector<indexType> &indices) const;

/// @brief Get the value at a certain entry in the tensor as an std::variant
/// @details This mainly exists so we can get the values of a tensor in python as pybind11 DOES NOT like templated
/// functions If using the c++ interface it is probably easier, faster and safer to use the templated getValue()
/// function.
[[nodiscard]] variantType getVariantValue(const std::vector<int> &indices) const;

/// @brief Get the number of dimensions in the tensor
[[nodiscard]] size_t getNdim() const;

/// @brief Get the batch dimension size of the tensor
/// @brief Get the size of the batch dimension of the tensor
[[nodiscard]] int getBatchDim() const;

/// @brief Get the shape of the tensor
Expand All @@ -302,6 +338,8 @@

private:
bool _hasBatchDim = false;
NTdtypes::scalarType _dType;
NTdtypes::deviceType _device;

// ###################################################
// ########## Tensor library specific stuff ##########
Expand All @@ -312,37 +350,84 @@
public:
/// @brief Get the value at a particular index of the tensor
/// @arg indices The indices of the value to set
template <typename T> inline T getValue(const std::vector<int> &indices)
template <typename T> inline T getValue(const std::vector<int> &indices) const
{
NT_PROFILE();

std::vector<at::indexing::TensorIndex> indicesVec;
indicesVec.reserve(indices.size());
for (const int &i : indices)
{
indicesVec.push_back(at::indexing::TensorIndex(i));
}

return _tensor.index(indicesVec).item<T>();
return _tensor.index(convertIndices(indices)).item<T>();
}

/// Get the value of a size 0 tensor (scalar)
template <typename T> inline T getValue()
template <typename T> inline T getValue() const
{

NT_PROFILE();

return _tensor.item<T>();
}

// return the underlying tensor with type determined by the backend library
[[nodiscard]] inline const torch::Tensor &getTensor() const
{

NT_PROFILE();

return _tensor;
}

private:
/// Set the underlying tensor, setting the relevant information like _dtype and _device
inline void setTensor(torch::Tensor tensor)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy diagnostics

Suggested change
inline void setTensor(torch::Tensor tensor)
inline void setTensor(const torch::Tensor &tensor)

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:58:5: warning: [clang-analyzer-optin.cplusplus.UninitializedObject]

2 uninitialized fields at the end of the constructor call

    Tensor(){};
    ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/tensor.hpp:342:26: note: uninitialized field 'this->_device'
    NTdtypes::deviceType _device;
                         ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/tensor.hpp:341:26: note: uninitialized field 'this->_dType'
    NTdtypes::scalarType _dType;
                         ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/torch-tensor.cpp:25:12: note: Calling default constructor for 'Tensor'
    Tensor ret;
           ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/tensor.hpp:58:5: note: 2 uninitialized fields at the end of the constructor call
    Tensor(){};
    ^

clang-tidy diagnostic

python/pyNuTens.cpp:22:1: warning: [cppcoreguidelines-avoid-non-const-global-variables]

variable 'pybind11_module_def_pyNuTens' is non-const and globally accessible, consider making it const

PYBIND11_MODULE(pyNuTens, m)
^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:392:44: note: expanded from macro 'PYBIND11_MODULE'
    static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name)            \
                                           ^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:312:40: note: expanded from macro 'PYBIND11_CONCAT'
#define PYBIND11_CONCAT(first, second) first##second
                                       ^
note: expanded from here

clang-tidy diagnostic

python/pyNuTens.cpp:22:1: warning: [cppcoreguidelines-pro-bounds-pointer-arithmetic]

do not use pointer arithmetic

PYBIND11_MODULE(pyNuTens, m)
^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:397:9: note: expanded from macro 'PYBIND11_MODULE'
        PYBIND11_CHECK_PYTHON_VERSION                                                             \
        ^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:322:17: note: expanded from macro 'PYBIND11_CHECK_PYTHON_VERSION'
            || (runtime_ver[len] >= '0' && runtime_ver[len] <= '9')) {                            \
                ^

{
NT_PROFILE();

_tensor = std::move(tensor);
_dType = NTdtypes::invScalarTypeMap.at(tensor.scalar_type());

Check warning on line 383 in nuTens/tensors/tensor.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter

nuTens/tensors/tensor.hpp:383:48 [bugprone-use-after-move]

'tensor' used after it was moved

Check warning on line 383 in nuTens/tensors/tensor.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter

nuTens/tensors/tensor.hpp:383:48 [clang-analyzer-cplusplus.Move]

Method called on moved-from object 'tensor'
_device = NTdtypes::invDeviceTypeMap.at(tensor.device().type());
}

/// Utility function to convert from a vector of ints to a vector of a10 tensor indices, which is needed for
/// accessing values of a tensor.
[[nodiscard]] inline std::vector<at::indexing::TensorIndex> convertIndices(const std::vector<int> &indices) const

Check warning on line 389 in nuTens/tensors/tensor.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter

nuTens/tensors/tensor.hpp:389:65 [readability-convert-member-functions-to-static]

method 'convertIndices' can be made static
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy diagnostics

Suggested change
[[nodiscard]] inline std::vector<at::indexing::TensorIndex> convertIndices(const std::vector<int> &indices) const
[[nodiscard]] static inline std::vector<at::indexing::TensorIndex> convertIndices(const std::vector<int> &indices)

clang-tidy diagnostic

nuTens/tensors/tensor.hpp:383:48: warning: [bugprone-use-after-move]

'tensor' used after it was moved

        _dType = NTdtypes::invScalarTypeMap.at(tensor.scalar_type());
                                               ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/tensor.hpp:382:17: note: move occurred here
        _tensor = std::move(tensor);
                ^

clang-tidy diagnostic

nuTens/tensors/tensor.hpp:383:48: warning: [clang-analyzer-cplusplus.Move]

Method called on moved-from object 'tensor'

        _dType = NTdtypes::invScalarTypeMap.at(tensor.scalar_type());
                                               ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/tensor.hpp:382:9: note: Object 'tensor' is moved
        _tensor = std::move(tensor);
        ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/tensor.hpp:383:48: note: Method called on moved-from object 'tensor'
        _dType = NTdtypes::invScalarTypeMap.at(tensor.scalar_type());
                                               ^

clang-tidy diagnostic

nuTens/tensors/torch-tensor.cpp:58:5: warning: [clang-analyzer-optin.cplusplus.UninitializedObject]

2 uninitialized fields at the end of the constructor call

    Tensor(){};
    ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/tensor.hpp:342:26: note: uninitialized field 'this->_device'
    NTdtypes::deviceType _device;
                         ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/tensor.hpp:341:26: note: uninitialized field 'this->_dType'
    NTdtypes::scalarType _dType;
                         ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/torch-tensor.cpp:25:12: note: Calling default constructor for 'Tensor'
    Tensor ret;
           ^
/home/runner/work/nuTens/nuTens/nuTens/tensors/tensor.hpp:58:5: note: 2 uninitialized fields at the end of the constructor call
    Tensor(){};
    ^

clang-tidy diagnostic

python/pyNuTens.cpp:22:1: warning: [cppcoreguidelines-avoid-non-const-global-variables]

variable 'pybind11_module_def_pyNuTens' is non-const and globally accessible, consider making it const

PYBIND11_MODULE(pyNuTens, m)
^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:392:44: note: expanded from macro 'PYBIND11_MODULE'
    static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name)            \
                                           ^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:312:40: note: expanded from macro 'PYBIND11_CONCAT'
#define PYBIND11_CONCAT(first, second) first##second
                                       ^
note: expanded from here

clang-tidy diagnostic

python/pyNuTens.cpp:22:1: warning: [cppcoreguidelines-pro-bounds-pointer-arithmetic]

do not use pointer arithmetic

PYBIND11_MODULE(pyNuTens, m)
^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:397:9: note: expanded from macro 'PYBIND11_MODULE'
        PYBIND11_CHECK_PYTHON_VERSION                                                             \
        ^
/home/runner/.local/lib/python3.10/site-packages/torch/include/pybind11/detail/common.h:322:17: note: expanded from macro 'PYBIND11_CHECK_PYTHON_VERSION'
            || (runtime_ver[len] >= '0' && runtime_ver[len] <= '9')) {                            \
                ^

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy diagnostics

Suggested change
[[nodiscard]] inline std::vector<at::indexing::TensorIndex> convertIndices(const std::vector<int> &indices) const
[[nodiscard]] static inline std::vector<at::indexing::TensorIndex> convertIndices(const std::vector<int> &indices)

{
NT_PROFILE();

std::vector<at::indexing::TensorIndex> indicesVec;
indicesVec.reserve(indices.size());
for (const int &i : indices)
{
indicesVec.push_back(at::indexing::TensorIndex(i));
}

return indicesVec;
}

/// Utility function to convert from a vector of ints to a vector of a10 tensor indices, which is needed for
/// accessing values of a tensor.
[[nodiscard]] inline std::vector<at::indexing::TensorIndex> convertIndices(

Check warning on line 405 in nuTens/tensors/tensor.hpp

View workflow job for this annotation

GitHub Actions / cpp-linter

nuTens/tensors/tensor.hpp:405:65 [readability-convert-member-functions-to-static]

method 'convertIndices' can be made static
const std::vector<Tensor::indexType> &indices) const
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy diagnostics

Suggested change
[[nodiscard]] inline std::vector<at::indexing::TensorIndex> convertIndices(
const std::vector<Tensor::indexType> &indices) const
[[nodiscard]] static inline std::vector<at::indexing::TensorIndex> convertIndices(
const std::vector<Tensor::indexType> &indices)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy diagnostics

Suggested change
[[nodiscard]] inline std::vector<at::indexing::TensorIndex> convertIndices(
const std::vector<Tensor::indexType> &indices) const
[[nodiscard]] static inline std::vector<at::indexing::TensorIndex> convertIndices(
const std::vector<Tensor::indexType> &indices)

{
NT_PROFILE();

std::vector<at::indexing::TensorIndex> indicesVec;
for (const Tensor::indexType &i : indices)
{
if (const int *index = std::get_if<int>(&i))
{
indicesVec.push_back(at::indexing::TensorIndex(*index));
}
else if (const std::string *index = std::get_if<std::string>(&i))
{
indicesVec.push_back(at::indexing::TensorIndex((*index).c_str()));
}
else
{
assert(false && "ERROR: Unsupported index type");
throw;
}
}

return indicesVec;
}

private:
torch::Tensor _tensor;
#endif
Expand Down
Loading
Loading