From c1289abb9cca5e817a92f51e84424ec74bf40512 Mon Sep 17 00:00:00 2001 From: davrot <54365609+davrot@users.noreply.github.com> Date: Sat, 30 Apr 2022 02:07:55 +0200 Subject: [PATCH] C++ module --- C++/HDynamicCNNManyIP.cpp | 289 ++++++++++++++++++++++++++++++ C++/HDynamicCNNManyIP.h | 71 ++++++++ C++/Makefile | 75 ++++++++ C++/PyHDynamicCNNManyIP.cpp | 44 +++++ C++/PySpikeGeneration2DManyIP.cpp | 44 +++++ C++/SpikeGeneration2DManyIP.cpp | 197 ++++++++++++++++++++ C++/SpikeGeneration2DManyIP.h | 66 +++++++ 7 files changed, 786 insertions(+) create mode 100644 C++/HDynamicCNNManyIP.cpp create mode 100644 C++/HDynamicCNNManyIP.h create mode 100644 C++/Makefile create mode 100644 C++/PyHDynamicCNNManyIP.cpp create mode 100644 C++/PySpikeGeneration2DManyIP.cpp create mode 100644 C++/SpikeGeneration2DManyIP.cpp create mode 100644 C++/SpikeGeneration2DManyIP.h diff --git a/C++/HDynamicCNNManyIP.cpp b/C++/HDynamicCNNManyIP.cpp new file mode 100644 index 0000000..5e4dad2 --- /dev/null +++ b/C++/HDynamicCNNManyIP.cpp @@ -0,0 +1,289 @@ +// MIT License +// Copyright 2022 University of Bremen +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +// THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// +// David Rotermund ( davrot@uni-bremen.de ) +// +// +// Release history: +// ================ +// 1.0.0 -- 01.05.2022: first release +// +// + +#include "HDynamicCNNManyIP.h" + +#include +#include +#include + +#include +#include +#include +#include + +HDynamicCNNManyIP::HDynamicCNNManyIP(){ + +}; + +HDynamicCNNManyIP::~HDynamicCNNManyIP(){ + +}; + +bool HDynamicCNNManyIP::update( + int64_t np_h_pointer_addr, int64_t np_h_dim_0, int64_t np_h_dim_1, + int64_t np_h_dim_2, int64_t np_h_dim_3, int64_t np_epsilon_xy_pointer_addr, + int64_t np_epsilon_xy_dim_0, int64_t np_epsilon_xy_dim_1, + int64_t np_epsilon_t_pointer_addr, int64_t np_epsilon_t_dim_0, + int64_t np_weights_pointer_addr, int64_t np_weights_dim_0, + int64_t np_weights_dim_1, int64_t np_input_pointer_addr, + int64_t np_input_dim_0, int64_t np_input_dim_1, int64_t np_input_dim_2, + int64_t np_input_dim_3, float *np_init_vector_pointer_ptr, + int64_t np_init_vector_dim_0, int64_t id_pattern) { + float *np_h_pointer = (float *)np_h_pointer_addr; + float *np_epsilon_xy_pointer = (float *)np_epsilon_xy_pointer_addr; + float *np_epsilon_t_pointer = (float *)np_epsilon_t_pointer_addr; + float *np_weights_pointer = (float *)np_weights_pointer_addr; + int64_t *np_input_pointer = (int64_t *)np_input_pointer_addr; + + int64_t number_of_pattern = np_input_dim_0; + + assert((id_pattern >= 0)); + assert((id_pattern < number_of_pattern)); + + assert((np_h_pointer != nullptr)); + assert((np_h_dim_0 > 0)); + assert((np_h_dim_1 > 0)); + assert((np_h_dim_2 > 0)); + assert((np_h_dim_3 > 0)); + + int64_t np_h_dim_c0 = np_h_dim_1 * np_h_dim_2 * np_h_dim_3; + int64_t np_h_dim_c1 = np_h_dim_2 * np_h_dim_3; + int64_t np_h_dim_c2 = np_h_dim_3; + + float *np_h_pointer_pattern; + float *np_h_pointer_pattern_0; + float *np_h_pointer_pattern_01; + + assert((np_epsilon_xy_pointer != nullptr)); + assert((np_epsilon_xy_dim_0 > 0)); + assert((np_epsilon_xy_dim_1 > 0)); + + int64_t np_epsilon_xy_dim_c0 = np_epsilon_xy_dim_1; + + float *np_epsilon_xy_pointer_0; + float *np_epsilon_xy_pointer_01; + + assert((np_epsilon_t_pointer != nullptr)); + assert((np_epsilon_t_dim_0 > 0)); + + assert((np_weights_pointer != nullptr)); + assert((np_weights_dim_0 > 0)); + assert((np_weights_dim_1 > 0)); + + int64_t np_weights_dim_c0 = np_weights_dim_1; + + float *w_ptr; + + assert((np_input_pointer != nullptr)); + assert((np_input_dim_0 > 0)); + assert((np_input_dim_1 > 0)); + assert((np_input_dim_2 > 0)); + assert((np_input_dim_3 > 0)); + + int64_t np_input_dim_c0 = np_input_dim_1 * np_input_dim_2 * np_input_dim_3; + int64_t np_input_dim_c1 = np_input_dim_2 * np_input_dim_3; + int64_t np_input_dim_c2 = np_input_dim_3; + + int64_t *np_input_pointer_pattern; + int64_t *np_input_pointer_pattern_0; + int64_t *np_input_pointer_pattern_01; + int64_t *np_input_pointer_pattern_01_spike; + + assert((np_init_vector_pointer_ptr != nullptr)); + assert((np_init_vector_dim_0 == np_weights_dim_1)); + + int64_t number_of_spikes = np_input_dim_1; + + int64_t h_dim = np_weights_dim_1; + + std::vector h_temp_vector; + h_temp_vector.resize(h_dim); + float *h_temp = h_temp_vector.data(); + + std::vector h_subsegment_vector; + h_subsegment_vector.resize(h_dim); + float *h_subsegment = h_subsegment_vector.data(); + + float h_temp_sum; + + int64_t id_0; + int64_t id_1; + int64_t id_spike; + int64_t counter; + + float temp_value; + + float epsilon_scale; + float epsilon_subsegment; + + // epsilon_subsegment = np_epsilon_xy_pointer[ + // id_0 * np_epsilon_xy_dim_c0 + + // id_1 ] + // * np_epsilon_t_pointer[id_spike]; + + // spike = np_input_pointer[ + // id_pattern * np_input_dim_c0 + + // id_spike * np_input_dim_c1 + + // id_0 * np_input_dim_c2 + + // id_1]; + + // w_ptr = np_weights_pointer + + // spike * np_weights_dim_c0; + + // h_ptr = np_h_pointer + + // id_pattern * np_h_dim_c0 + + // id_0 * np_h_dim_c2 + + // id_1; + // // 0 * np_h_dim_c1 + + + np_input_pointer_pattern = np_input_pointer + id_pattern * np_input_dim_c0; + np_h_pointer_pattern = np_h_pointer + id_pattern * np_h_dim_c0; + + for (id_0 = 0; id_0 < np_input_dim_2; id_0++) { + np_epsilon_xy_pointer_0 = + np_epsilon_xy_pointer + id_0 * np_epsilon_xy_dim_c0; + + np_h_pointer_pattern_0 = np_h_pointer_pattern + id_0 * np_h_dim_c2; + + np_input_pointer_pattern_0 = + np_input_pointer_pattern + id_0 * np_input_dim_c2; + + for (id_1 = 0; id_1 < np_input_dim_3; id_1++) { + np_epsilon_xy_pointer_01 = np_epsilon_xy_pointer_0 + id_1; + + np_h_pointer_pattern_01 = np_h_pointer_pattern_0 + id_1; + + np_input_pointer_pattern_01 = np_input_pointer_pattern_0 + id_1; + + memcpy(h_subsegment, np_init_vector_pointer_ptr, sizeof(float) * h_dim); + + epsilon_scale = 1.0; + + for (id_spike = 0; id_spike < number_of_spikes; id_spike++) { + if (epsilon_scale > 1E10) { + temp_value = 1.0 / epsilon_scale; + +#pragma omp simd + for (counter = 0; counter < h_dim; counter++) { + h_subsegment[counter] *= temp_value; + } + + epsilon_scale = 1.0; + } + + epsilon_subsegment = + np_epsilon_xy_pointer_01[0] * np_epsilon_t_pointer[id_spike]; + + np_input_pointer_pattern_01_spike = + np_input_pointer_pattern_01 + id_spike * np_input_dim_c1; + + w_ptr = np_weights_pointer + + np_input_pointer_pattern_01_spike[0] * np_weights_dim_c0; + + memcpy(h_temp, h_subsegment, sizeof(float) * h_dim); + +#pragma omp simd + for (counter = 0; counter < h_dim; counter++) { + h_temp[counter] *= w_ptr[counter]; + } + + h_temp_sum = 0.0; +#pragma omp simd reduction(+ : h_temp_sum) + for (counter = 0; counter < h_dim; counter++) { + h_temp_sum += h_temp[counter]; + } + + if (h_temp_sum > 1E-10) { + temp_value = epsilon_scale * epsilon_subsegment / h_temp_sum; + +#pragma omp simd + for (counter = 0; counter < h_dim; counter++) { + h_temp[counter] *= temp_value; + } + +#pragma omp simd + for (counter = 0; counter < h_dim; counter++) { + h_subsegment[counter] += h_temp[counter]; + } + + epsilon_scale *= 1.0 + epsilon_subsegment; + // IF + } + // spike End + } + + temp_value = 1.0 / epsilon_scale; +#pragma omp simd + for (counter = 0; counter < h_dim; counter++) { + np_h_pointer_pattern_01[counter * np_h_dim_c1] = + h_subsegment[counter] * temp_value; + } + + // id_1 End + } + + // id_0 End + } + + return true; +}; + +bool HDynamicCNNManyIP::update_with_init_vector_multi_pattern( + int64_t np_h_pointer_addr, int64_t np_h_dim_0, int64_t np_h_dim_1, + int64_t np_h_dim_2, int64_t np_h_dim_3, int64_t np_epsilon_xy_pointer_addr, + int64_t np_epsilon_xy_dim_0, int64_t np_epsilon_xy_dim_1, + int64_t np_epsilon_t_pointer_addr, int64_t np_epsilon_t_dim_0, + int64_t np_weights_pointer_addr, int64_t np_weights_dim_0, + int64_t np_weights_dim_1, int64_t np_input_pointer_addr, + int64_t np_input_dim_0, int64_t np_input_dim_1, int64_t np_input_dim_2, + int64_t np_input_dim_3, int64_t np_init_vector_pointer_addr, + int64_t np_init_vector_dim_0, int64_t number_of_processes) { + int64_t number_of_pattern = np_input_dim_0; + int64_t pattern_id; + + int64_t h_dim = np_init_vector_dim_0; + float *h_init_ptr = (float *)np_init_vector_pointer_addr; + + omp_set_num_threads(number_of_processes); + +#pragma omp parallel for + for (pattern_id = 0; pattern_id < number_of_pattern; pattern_id++) { + update(np_h_pointer_addr, np_h_dim_0, np_h_dim_1, np_h_dim_2, np_h_dim_3, + np_epsilon_xy_pointer_addr, np_epsilon_xy_dim_0, np_epsilon_xy_dim_1, + np_epsilon_t_pointer_addr, np_epsilon_t_dim_0, + np_weights_pointer_addr, np_weights_dim_0, np_weights_dim_1, + np_input_pointer_addr, np_input_dim_0, np_input_dim_1, + np_input_dim_2, np_input_dim_3, h_init_ptr, h_dim, pattern_id); + } + + return true; +}; diff --git a/C++/HDynamicCNNManyIP.h b/C++/HDynamicCNNManyIP.h new file mode 100644 index 0000000..6fb15ad --- /dev/null +++ b/C++/HDynamicCNNManyIP.h @@ -0,0 +1,71 @@ +// MIT License +// Copyright 2022 University of Bremen +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +// THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// +// David Rotermund ( davrot@uni-bremen.de ) +// +// +// Release history: +// ================ +// 1.0.0 -- 01.05.2022: first release +// +// + +#ifndef SRC_HDYNAMICCNNMANYIP_H_ +#define SRC_HDYNAMICCNNMANYIP_H_ + +#include + +#include +#include + +class HDynamicCNNManyIP { + public: + HDynamicCNNManyIP(); + ~HDynamicCNNManyIP(); + + bool update(int64_t np_h_pointer_addr, int64_t np_h_dim_0, int64_t np_h_dim_1, + int64_t np_h_dim_2, int64_t np_h_dim_3, + int64_t np_epsilon_xy_pointer_addr, int64_t np_epsilon_xy_dim_0, + int64_t np_epsilon_xy_dim_1, int64_t np_epsilon_t_pointer_addr, + int64_t np_epsilon_t_dim_0, int64_t np_weights_pointer_addr, + int64_t np_weights_dim_0, int64_t np_weights_dim_1, + int64_t np_input_pointer_addr, int64_t np_input_dim_0, + int64_t np_input_dim_1, int64_t np_input_dim_2, + int64_t np_input_dim_3, float *np_init_vector_pointer_ptr, + int64_t np_init_vector_dim_0, int64_t id_pattern); + + bool update_with_init_vector_multi_pattern( + int64_t np_h_pointer_addr, int64_t np_h_dim_0, int64_t np_h_dim_1, + int64_t np_h_dim_2, int64_t np_h_dim_3, + int64_t np_epsilon_xy_pointer_addr, int64_t np_epsilon_xy_dim_0, + int64_t np_epsilon_xy_dim_1, int64_t np_epsilon_t_pointer_addr, + int64_t np_epsilon_t_dim_0, int64_t np_weights_pointer_addr, + int64_t np_weights_dim_0, int64_t np_weights_dim_1, + int64_t np_input_pointer_addr, int64_t np_input_dim_0, + int64_t np_input_dim_1, int64_t np_input_dim_2, int64_t np_input_dim_3, + int64_t np_init_vector_pointer_addr, int64_t np_init_vector_dim_0, + int64_t number_of_processes); + + private: +}; + +#endif /* SRC_HDYNAMICCNNMANYIP_H_ */ \ No newline at end of file diff --git a/C++/Makefile b/C++/Makefile new file mode 100644 index 0000000..a00d72a --- /dev/null +++ b/C++/Makefile @@ -0,0 +1,75 @@ +# MIT License +# Copyright 2022 University of Bremen +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +# THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# +# David Rotermund ( davrot@uni-bremen.de ) +# +# +# Release history: +# ================ +# 1.0.0 -- 01.05.2022: first release +# +# + +# Change to your python bin directory (tested with Python 3.10.4) +PYBIN=~/P3.10/bin/ +COMPILER=clang++ + +PYBIND11INCLUDE=`$(PYBIN)python3 -m pybind11 --includes` + +PARAMETERS= -O3 -std=c++14 -fPIC $(PYBIND11INCLUDE) -Wall -fopenmp=libomp + + +all: PyHDynamicCNNManyIP \ + PySpikeGeneration2DManyIP \ + +####################### + +HDynamicCNNManyIP.o: HDynamicCNNManyIP.h HDynamicCNNManyIP.cpp + $(COMPILER) $(PARAMETERS) -c HDynamicCNNManyIP.cpp -o HDynamicCNNManyIP.o + +PyHDynamicCNNManyIP.o: HDynamicCNNManyIP.h PyHDynamicCNNManyIP.cpp + $(COMPILER) $(PARAMETERS) -c PyHDynamicCNNManyIP.cpp -o PyHDynamicCNNManyIP.o + +PyHDynamicCNNManyIP: HDynamicCNNManyIP.o PyHDynamicCNNManyIP.o + $(COMPILER) -shared -o PyHDynamicCNNManyIP HDynamicCNNManyIP.o PyHDynamicCNNManyIP.o -lm -lomp -lstdc++ -Wall + cp PyHDynamicCNNManyIP ../PyHDynamicCNNManyIP`$(PYBIN)python3-config --extension-suffix` + +####################### + +SpikeGeneration2DManyIP.o: SpikeGeneration2DManyIP.h SpikeGeneration2DManyIP.cpp + $(COMPILER) $(PARAMETERS) -c SpikeGeneration2DManyIP.cpp -o SpikeGeneration2DManyIP.o + +PySpikeGeneration2DManyIP.o: SpikeGeneration2DManyIP.h PySpikeGeneration2DManyIP.cpp + $(COMPILER) $(PARAMETERS) -c PySpikeGeneration2DManyIP.cpp -o PySpikeGeneration2DManyIP.o + +PySpikeGeneration2DManyIP: SpikeGeneration2DManyIP.o PySpikeGeneration2DManyIP.o + $(COMPILER) -shared -o PySpikeGeneration2DManyIP SpikeGeneration2DManyIP.o PySpikeGeneration2DManyIP.o -lm -lomp -lstdc++ -Wall + cp PySpikeGeneration2DManyIP ../PySpikeGeneration2DManyIP`$(PYBIN)python3-config --extension-suffix` + + +####################### + +clean: + rm -f PyHDynamicCNNManyIP + rm -f PySpikeGeneration2DManyIP + rm -f *.o + diff --git a/C++/PyHDynamicCNNManyIP.cpp b/C++/PyHDynamicCNNManyIP.cpp new file mode 100644 index 0000000..5a03532 --- /dev/null +++ b/C++/PyHDynamicCNNManyIP.cpp @@ -0,0 +1,44 @@ +// MIT License +// Copyright 2022 University of Bremen +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +// THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// +// David Rotermund ( davrot@uni-bremen.de ) +// +// +// Release history: +// ================ +// 1.0.0 -- 01.05.2022: first release +// +// + +#include + +#include "HDynamicCNNManyIP.h" + +namespace py = pybind11; + +PYBIND11_MODULE(PyHDynamicCNNManyIP, m) { + m.doc() = "HDynamicCNNManyIP Module"; + py::class_(m, "HDynamicCNNManyIP") + .def(py::init<>()) + .def("update_with_init_vector_multi_pattern", + &HDynamicCNNManyIP::update_with_init_vector_multi_pattern); +} \ No newline at end of file diff --git a/C++/PySpikeGeneration2DManyIP.cpp b/C++/PySpikeGeneration2DManyIP.cpp new file mode 100644 index 0000000..b2438c7 --- /dev/null +++ b/C++/PySpikeGeneration2DManyIP.cpp @@ -0,0 +1,44 @@ +// MIT License +// Copyright 2022 University of Bremen +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +// THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// +// David Rotermund ( davrot@uni-bremen.de ) +// +// +// Release history: +// ================ +// 1.0.0 -- 01.05.2022: first release +// +// + +#include + +#include "SpikeGeneration2DManyIP.h" + +namespace py = pybind11; + +PYBIND11_MODULE(PySpikeGeneration2DManyIP, m) { + m.doc() = "SpikeGeneration2DManyIP Module"; + py::class_(m, "SpikeGeneration2DManyIP") + .def(py::init<>()) + .def("spike_generation_multi_pattern", + &SpikeGeneration2DManyIP::spike_generation_multi_pattern); +} diff --git a/C++/SpikeGeneration2DManyIP.cpp b/C++/SpikeGeneration2DManyIP.cpp new file mode 100644 index 0000000..8e8be68 --- /dev/null +++ b/C++/SpikeGeneration2DManyIP.cpp @@ -0,0 +1,197 @@ +// MIT License +// Copyright 2022 University of Bremen +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +// THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// +// David Rotermund ( davrot@uni-bremen.de ) +// +// +// Release history: +// ================ +// 1.0.0 -- 01.05.2022: first release +// +// + +#include "SpikeGeneration2DManyIP.h" + +#include +#include +#include + +#include +#include +#include +#include + +SpikeGeneration2DManyIP::SpikeGeneration2DManyIP(){ + +}; + +SpikeGeneration2DManyIP::~SpikeGeneration2DManyIP(){ + +}; + +bool SpikeGeneration2DManyIP::spike_generation_multi_pattern( + int64_t np_input_pointer_addr, int64_t np_input_dim_0, + int64_t np_input_dim_1, int64_t np_input_dim_2, int64_t np_input_dim_3, + int64_t np_random_values_pointer_addr, int64_t np_random_values_dim_0, + int64_t np_random_values_dim_1, int64_t np_random_values_dim_2, + int64_t np_random_values_dim_3, int64_t np_output_pointer_addr, + int64_t np_output_dim_0, int64_t np_output_dim_1, int64_t np_output_dim_2, + int64_t np_output_dim_3, int64_t number_of_cpu_processes) { + int64_t number_of_pattern = np_input_dim_0; + int64_t pattern_id; + + omp_set_num_threads(number_of_cpu_processes); + +#pragma omp parallel for + for (pattern_id = 0; pattern_id < number_of_pattern; pattern_id++) { + spike_generation( + np_input_pointer_addr, np_input_dim_0, np_input_dim_1, np_input_dim_2, + np_input_dim_3, np_random_values_pointer_addr, np_random_values_dim_0, + np_random_values_dim_1, np_random_values_dim_2, np_random_values_dim_3, + np_output_pointer_addr, np_output_dim_0, np_output_dim_1, + np_output_dim_2, np_output_dim_3, pattern_id); + } + + return true; +}; + +bool SpikeGeneration2DManyIP::spike_generation( + int64_t np_input_pointer_addr, int64_t np_input_dim_0, + int64_t np_input_dim_1, int64_t np_input_dim_2, int64_t np_input_dim_3, + int64_t np_random_values_pointer_addr, int64_t np_random_values_dim_0, + int64_t np_random_values_dim_1, int64_t np_random_values_dim_2, + int64_t np_random_values_dim_3, int64_t np_output_pointer_addr, + int64_t np_output_dim_0, int64_t np_output_dim_1, int64_t np_output_dim_2, + int64_t np_output_dim_3, int64_t id_pattern) { + float *np_input_pointer = (float *)np_input_pointer_addr; + float *np_random_values_pointer = (float *)np_random_values_pointer_addr; + int64_t *np_output_pointer = (int64_t *)np_output_pointer_addr; + + assert((id_pattern >= 0)); + assert((id_pattern < np_input_dim_0)); + + // Input + assert((np_input_pointer != nullptr)); + assert((np_input_dim_0 > 0)); + assert((np_input_dim_1 > 0)); + assert((np_input_dim_2 > 0)); + assert((np_input_dim_3 > 0)); + + int64_t np_input_dim_c0 = np_input_dim_1 * np_input_dim_2 * np_input_dim_3; + int64_t np_input_dim_c1 = np_input_dim_2 * np_input_dim_3; + int64_t np_input_dim_c2 = np_input_dim_3; + + // Random + assert((np_random_values_pointer != nullptr)); + assert((np_random_values_dim_0 > 0)); + assert((np_random_values_dim_1 > 0)); + assert((np_random_values_dim_2 > 0)); + assert((np_random_values_dim_3 > 0)); + + int64_t np_random_values_dim_c0 = + np_random_values_dim_1 * np_random_values_dim_2 * np_random_values_dim_3; + int64_t np_random_values_dim_c1 = + np_random_values_dim_2 * np_random_values_dim_3; + int64_t np_random_values_dim_c2 = np_random_values_dim_3; + + // Output + assert((np_output_pointer != nullptr)); + assert((np_output_dim_0 > 0)); + assert((np_output_dim_1 > 0)); + assert((np_output_dim_2 > 0)); + assert((np_output_dim_3 > 0)); + + int64_t np_output_dim_c0 = + np_output_dim_1 * np_output_dim_2 * np_output_dim_3; + int64_t np_output_dim_c1 = np_output_dim_2 * np_output_dim_3; + int64_t np_output_dim_c2 = np_output_dim_3; + + // ------------------------------- + + int64_t h_dim = np_input_dim_1; + int64_t spike_dim = np_output_dim_1; + + std::vector temp_p; + temp_p.resize(h_dim); + float *temp_p_ptr = temp_p.data(); + + std::vector temp_out; + temp_out.resize(spike_dim); + int64_t *temp_out_ptr = temp_out.data(); + + std::vector temp_rand; + temp_rand.resize(spike_dim); + float *temp_rand_ptr = temp_rand.data(); + + int64_t counter; + + int64_t counter_x = 0; + int64_t counter_y = 0; + + float *p_ptr = nullptr; + int64_t *out_ptr = nullptr; + float *rand_ptr = nullptr; + + std::vector::iterator position_iterator; + + for (counter_x = 0; counter_x < np_output_dim_2; counter_x++) { + for (counter_y = 0; counter_y < np_output_dim_3; counter_y++) { + p_ptr = np_input_pointer + id_pattern * np_input_dim_c0 + + counter_x * np_input_dim_c2 + counter_y; + // + counter * np_input_dim_c1 + + out_ptr = np_output_pointer + id_pattern * np_output_dim_c0 + + counter_x * np_output_dim_c2 + counter_y; + // + counter * np_output_dim_c1 + + rand_ptr = np_random_values_pointer + + id_pattern * np_random_values_dim_c0 + + counter_x * np_random_values_dim_c2 + counter_y; + // + counter * np_random_values_dim_c1 + +#pragma omp simd + for (counter = 0; counter < h_dim; counter++) { + temp_p_ptr[counter] = p_ptr[counter * np_input_dim_c1]; + } + +#pragma omp simd + for (counter = 0; counter < spike_dim; counter++) { + temp_rand_ptr[counter] = rand_ptr[counter * np_random_values_dim_c1]; + } + + // ---------------------------- + for (counter = 0; counter < spike_dim; counter++) { + position_iterator = std::lower_bound(temp_p.begin(), temp_p.end(), + temp_rand_ptr[counter]); + temp_out_ptr[counter] = position_iterator - temp_p.begin(); + } + // ---------------------------- + +#pragma omp simd + for (counter = 0; counter < spike_dim; counter++) { + out_ptr[counter * np_output_dim_c1] = temp_out_ptr[counter]; + } + } + } + + return true; +}; diff --git a/C++/SpikeGeneration2DManyIP.h b/C++/SpikeGeneration2DManyIP.h new file mode 100644 index 0000000..99e7810 --- /dev/null +++ b/C++/SpikeGeneration2DManyIP.h @@ -0,0 +1,66 @@ +// MIT License +// Copyright 2022 University of Bremen +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +// THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// +// David Rotermund ( davrot@uni-bremen.de ) +// +// +// Release history: +// ================ +// 1.0.0 -- 01.05.2022: first release +// +// + +#ifndef SRC_SPIKEGENERATION2DMANYIP_H_ +#define SRC_SPIKEGENERATION2DMANYIP_H_ + +#include + +#include +#include + +class SpikeGeneration2DManyIP { + public: + SpikeGeneration2DManyIP(); + ~SpikeGeneration2DManyIP(); + + bool spike_generation_multi_pattern( + int64_t np_input_pointer_addr, int64_t np_input_dim_0, + int64_t np_input_dim_1, int64_t np_input_dim_2, int64_t np_input_dim_3, + int64_t np_random_values_pointer_addr, int64_t np_random_values_dim_0, + int64_t np_random_values_dim_1, int64_t np_random_values_dim_2, + int64_t np_random_values_dim_3, int64_t np_output_pointer_addr, + int64_t np_output_dim_0, int64_t np_output_dim_1, int64_t np_output_dim_2, + int64_t np_output_dim_3, int64_t number_of_cpu_processes); + + bool spike_generation( + int64_t np_input_pointer_addr, int64_t np_input_dim_0, + int64_t np_input_dim_1, int64_t np_input_dim_2, int64_t np_input_dim_3, + int64_t np_random_values_pointer_addr, int64_t np_random_values_dim_0, + int64_t np_random_values_dim_1, int64_t np_random_values_dim_2, + int64_t np_random_values_dim_3, int64_t np_output_pointer_addr, + int64_t np_output_dim_0, int64_t np_output_dim_1, int64_t np_output_dim_2, + int64_t np_output_dim_3, int64_t id_pattern); + + private: +}; + +#endif /* SRC_SPIKEGENERATION2DMANYIP_H_ */ \ No newline at end of file