feat: Implement a custom MetaAllocator for uLib::Vector to enable GPU memory management and integrate CUDA support into the build system.
This commit is contained in:
@@ -22,8 +22,10 @@ if(USE_CUDA)
|
|||||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=20012\"")
|
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=20012\"")
|
||||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=20014\"")
|
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=20014\"")
|
||||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=20015\"")
|
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=20015\"")
|
||||||
|
find_package(CUDAToolkit REQUIRED)
|
||||||
enable_language(CUDA)
|
enable_language(CUDA)
|
||||||
set(CMAKE_CUDA_ARCHITECTURES 61)
|
set(CMAKE_CUDA_ARCHITECTURES 61)
|
||||||
|
include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
|
||||||
add_compile_definitions(USE_CUDA)
|
add_compile_definitions(USE_CUDA)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
set(HEADERS Archives.h Array.h Collection.h Debug.h Export.h Function.h Macros.h Mpl.h Object.h Options.h Serializable.h Signal.h Singleton.h SmartPointer.h StaticInterface.h StringReader.h Types.h Uuid.h Vector.h)
|
set(HEADERS Archives.h Array.h Collection.h DataAllocator.h Debug.h Export.h Function.h Macros.h Mpl.h Object.h Options.h Serializable.h Signal.h Singleton.h SmartPointer.h StaticInterface.h StringReader.h Types.h Uuid.h Vector.h)
|
||||||
|
|
||||||
set(SOURCES Archives.cpp Debug.cpp Object.cpp Options.cpp Serializable.cpp Signal.cpp Uuid.cpp)
|
set(SOURCES Archives.cpp Debug.cpp Object.cpp Options.cpp Serializable.cpp Signal.cpp Uuid.cpp)
|
||||||
|
|
||||||
@@ -13,6 +13,10 @@ add_library(${libname} SHARED ${SOURCES})
|
|||||||
set_target_properties(${libname} PROPERTIES
|
set_target_properties(${libname} PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
SOVERSION ${PROJECT_SOVERSION})
|
SOVERSION ${PROJECT_SOVERSION})
|
||||||
|
if(USE_CUDA)
|
||||||
|
set(LIBRARIES ${LIBRARIES} CUDA::cudart)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${libname} ${LIBRARIES})
|
target_link_libraries(${libname} ${LIBRARIES})
|
||||||
|
|
||||||
install(TARGETS ${libname}
|
install(TARGETS ${libname}
|
||||||
|
|||||||
@@ -42,20 +42,26 @@ enum class MemoryDevice { RAM, VRAM };
|
|||||||
|
|
||||||
template <typename T> class DataAllocator {
|
template <typename T> class DataAllocator {
|
||||||
public:
|
public:
|
||||||
DataAllocator()
|
DataAllocator(size_t size = 0, bool owns_objects = true)
|
||||||
: m_Size(0), m_RamData(nullptr), m_VramData(nullptr),
|
: m_Size(size), m_RamData(nullptr), m_VramData(nullptr),
|
||||||
m_Device(MemoryDevice::RAM) {}
|
m_Device(MemoryDevice::RAM), m_OwnsObjects(owns_objects) {
|
||||||
|
if (m_Size > 0) {
|
||||||
DataAllocator(size_t size)
|
if (m_OwnsObjects)
|
||||||
: m_Size(size), m_RamData(new T[size]()), m_VramData(nullptr),
|
m_RamData = new T[m_Size]();
|
||||||
m_Device(MemoryDevice::RAM) {}
|
else
|
||||||
|
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DataAllocator(const DataAllocator<T> &other)
|
DataAllocator(const DataAllocator<T> &other)
|
||||||
: m_Size(other.m_Size), m_RamData(nullptr), m_VramData(nullptr),
|
: m_Size(other.m_Size), m_RamData(nullptr), m_VramData(nullptr),
|
||||||
m_Device(other.m_Device) {
|
m_Device(other.m_Device), m_OwnsObjects(other.m_OwnsObjects) {
|
||||||
if (m_Size > 0) {
|
if (m_Size > 0) {
|
||||||
if (other.m_RamData) {
|
if (other.m_RamData) {
|
||||||
|
if (m_OwnsObjects)
|
||||||
m_RamData = new T[m_Size];
|
m_RamData = new T[m_Size];
|
||||||
|
else
|
||||||
|
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
||||||
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
|
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
|
||||||
}
|
}
|
||||||
#ifdef USE_CUDA
|
#ifdef USE_CUDA
|
||||||
@@ -70,7 +76,10 @@ public:
|
|||||||
|
|
||||||
~DataAllocator() {
|
~DataAllocator() {
|
||||||
if (m_RamData) {
|
if (m_RamData) {
|
||||||
|
if (m_OwnsObjects)
|
||||||
delete[] m_RamData;
|
delete[] m_RamData;
|
||||||
|
else
|
||||||
|
::operator delete(m_RamData);
|
||||||
}
|
}
|
||||||
#ifdef USE_CUDA
|
#ifdef USE_CUDA
|
||||||
if (m_VramData) {
|
if (m_VramData) {
|
||||||
@@ -81,11 +90,16 @@ public:
|
|||||||
|
|
||||||
DataAllocator &operator=(const DataAllocator &other) {
|
DataAllocator &operator=(const DataAllocator &other) {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
|
m_OwnsObjects = other.m_OwnsObjects;
|
||||||
resize(other.m_Size);
|
resize(other.m_Size);
|
||||||
m_Device = other.m_Device;
|
m_Device = other.m_Device;
|
||||||
if (other.m_RamData) {
|
if (other.m_RamData) {
|
||||||
if (!m_RamData)
|
if (!m_RamData) {
|
||||||
|
if (m_OwnsObjects)
|
||||||
m_RamData = new T[m_Size];
|
m_RamData = new T[m_Size];
|
||||||
|
else
|
||||||
|
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
||||||
|
}
|
||||||
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
|
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
|
||||||
}
|
}
|
||||||
#ifdef USE_CUDA
|
#ifdef USE_CUDA
|
||||||
@@ -103,8 +117,12 @@ public:
|
|||||||
void MoveToRAM() {
|
void MoveToRAM() {
|
||||||
if (m_Device == MemoryDevice::RAM)
|
if (m_Device == MemoryDevice::RAM)
|
||||||
return;
|
return;
|
||||||
if (!m_RamData && m_Size > 0)
|
if (!m_RamData && m_Size > 0) {
|
||||||
|
if (m_OwnsObjects)
|
||||||
m_RamData = new T[m_Size]();
|
m_RamData = new T[m_Size]();
|
||||||
|
else
|
||||||
|
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
||||||
|
}
|
||||||
#ifdef USE_CUDA
|
#ifdef USE_CUDA
|
||||||
if (m_VramData && m_Size > 0) {
|
if (m_VramData && m_Size > 0) {
|
||||||
cudaMemcpy(m_RamData, m_VramData, m_Size * sizeof(T),
|
cudaMemcpy(m_RamData, m_VramData, m_Size * sizeof(T),
|
||||||
@@ -137,7 +155,11 @@ public:
|
|||||||
T *newVram = nullptr;
|
T *newVram = nullptr;
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
|
if (m_OwnsObjects)
|
||||||
newRam = new T[size]();
|
newRam = new T[size]();
|
||||||
|
else
|
||||||
|
newRam = static_cast<T *>(::operator new(size * sizeof(T)));
|
||||||
|
|
||||||
if (m_RamData) {
|
if (m_RamData) {
|
||||||
std::memcpy(newRam, m_RamData, std::min(m_Size, size) * sizeof(T));
|
std::memcpy(newRam, m_RamData, std::min(m_Size, size) * sizeof(T));
|
||||||
}
|
}
|
||||||
@@ -151,8 +173,12 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_RamData)
|
if (m_RamData) {
|
||||||
|
if (m_OwnsObjects)
|
||||||
delete[] m_RamData;
|
delete[] m_RamData;
|
||||||
|
else
|
||||||
|
::operator delete(m_RamData);
|
||||||
|
}
|
||||||
#ifdef USE_CUDA
|
#ifdef USE_CUDA
|
||||||
if (m_VramData)
|
if (m_VramData)
|
||||||
cudaFree(m_VramData);
|
cudaFree(m_VramData);
|
||||||
@@ -225,6 +251,7 @@ private:
|
|||||||
T *m_RamData;
|
T *m_RamData;
|
||||||
T *m_VramData;
|
T *m_VramData;
|
||||||
MemoryDevice m_Device;
|
MemoryDevice m_Device;
|
||||||
|
bool m_OwnsObjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace uLib
|
} // namespace uLib
|
||||||
@@ -23,33 +23,115 @@
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef U_CORE_VECTOR_H
|
#ifndef U_CORE_VECTOR_H
|
||||||
#define U_CORE_VECTOR_H
|
#define U_CORE_VECTOR_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Core/DataAllocator.h>
|
||||||
|
|
||||||
#include <Core/StaticInterface.h>
|
|
||||||
#include <Core/SmartPointer.h>
|
|
||||||
#include <Core/CommaInitializer.h>
|
#include <Core/CommaInitializer.h>
|
||||||
|
#include <Core/SmartPointer.h>
|
||||||
|
#include <Core/StaticInterface.h>
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
|
|
||||||
|
// MetaAllocator Implementation ...
|
||||||
|
template <typename T> class MetaAllocator {
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = T *;
|
||||||
|
using const_pointer = const T *;
|
||||||
|
using reference = T &;
|
||||||
|
using const_reference = const T &;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
|
||||||
|
template <class U> struct rebind {
|
||||||
|
using other = MetaAllocator<U>;
|
||||||
|
};
|
||||||
|
|
||||||
|
MetaAllocator() noexcept = default;
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
constexpr MetaAllocator(const MetaAllocator<U> &) noexcept {}
|
||||||
|
|
||||||
|
T *allocate(std::size_t n) {
|
||||||
|
if (n == 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
DataAllocator<T> *da = new DataAllocator<T>(n, false);
|
||||||
|
T *ptr = da->GetRAMData();
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(GetMutex());
|
||||||
|
GetAllocationMap()[ptr] = da;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(T *p, std::size_t /*n*/) noexcept {
|
||||||
|
if (!p)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(GetMutex());
|
||||||
|
auto &map = GetAllocationMap();
|
||||||
|
auto it = map.find(p);
|
||||||
|
if (it != map.end()) {
|
||||||
|
delete it->second;
|
||||||
|
map.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DataAllocator<T> *GetDataAllocator(T *p) {
|
||||||
|
if (!p)
|
||||||
|
return nullptr;
|
||||||
|
std::lock_guard<std::mutex> lock(GetMutex());
|
||||||
|
auto &map = GetAllocationMap();
|
||||||
|
auto it = map.find(p);
|
||||||
|
if (it != map.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::map<T *, DataAllocator<T> *> &GetAllocationMap() {
|
||||||
|
static std::map<T *, DataAllocator<T> *> allocMap;
|
||||||
|
return allocMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::mutex &GetMutex() {
|
||||||
|
static std::mutex mtx;
|
||||||
|
return mtx;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
bool operator==(const MetaAllocator<T> &, const MetaAllocator<U> &) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template <class T, class U>
|
||||||
|
bool operator!=(const MetaAllocator<T> &, const MetaAllocator<U> &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Vector Implemetation ... wraps std::vector
|
// Vector Implemetation ... wraps std::vector
|
||||||
template <typename T>
|
template <typename T> class Vector : public std::vector<T, MetaAllocator<T>> {
|
||||||
class Vector : public std::vector<T, std::allocator<T> >
|
typedef std::vector<T, MetaAllocator<T>> BaseClass;
|
||||||
{
|
typedef MetaAllocator<T> Allocator;
|
||||||
typedef std::vector< T,std::allocator<T> > BaseClass;
|
|
||||||
typedef std::allocator<T> Allocator;
|
|
||||||
public:
|
public:
|
||||||
typedef T TypeData;
|
typedef T TypeData;
|
||||||
typedef __gnu_cxx::__normal_iterator<T *, BaseClass> Iterator;
|
typedef __gnu_cxx::__normal_iterator<T *, BaseClass> Iterator;
|
||||||
typedef __gnu_cxx::__normal_iterator<const T *, BaseClass> ConstIterator;
|
typedef __gnu_cxx::__normal_iterator<const T *, BaseClass> ConstIterator;
|
||||||
|
|
||||||
typedef CommaInitializer<Vector<T>, T> VectorCommaInit;
|
typedef CommaInitializer<Vector<T>, T> VectorCommaInit;
|
||||||
|
typedef typename BaseClass::iterator iterator;
|
||||||
|
typedef typename BaseClass::const_iterator const_iterator;
|
||||||
|
typedef typename BaseClass::size_type size_type;
|
||||||
|
typedef typename BaseClass::reference reference;
|
||||||
|
|
||||||
Vector(unsigned int size) : BaseClass(size) {}
|
Vector(unsigned int size) : BaseClass(size) {}
|
||||||
Vector(unsigned int size, T &value) : BaseClass(size, value) {}
|
Vector(unsigned int size, T &value) : BaseClass(size, value) {}
|
||||||
@@ -59,23 +141,187 @@ public:
|
|||||||
return VectorCommaInit(this, scalar);
|
return VectorCommaInit(this, scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MoveToVRAM() {
|
||||||
|
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
|
||||||
|
alloc->MoveToVRAM();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveToRAM() {
|
||||||
|
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
|
||||||
|
alloc->MoveToRAM();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T *GetVRAMData() {
|
||||||
|
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
|
||||||
|
return alloc->GetVRAMData();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T *GetVRAMData() const {
|
||||||
|
if (auto alloc = MetaAllocator<T>::GetDataAllocator(
|
||||||
|
const_cast<T *>(BaseClass::data()))) {
|
||||||
|
return alloc->GetVRAMData();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
inline void PrintSelf(std::ostream &o);
|
inline void PrintSelf(std::ostream &o);
|
||||||
|
|
||||||
|
// Overrides for auto-sync //
|
||||||
|
T &operator[](size_t i) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::operator[](i);
|
||||||
|
}
|
||||||
|
const T &operator[](size_t i) const {
|
||||||
|
const_cast<Vector *>(this)->MoveToRAM();
|
||||||
|
return BaseClass::operator[](i);
|
||||||
|
}
|
||||||
|
T &at(size_t i) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::at(i);
|
||||||
|
}
|
||||||
|
const T &at(size_t i) const {
|
||||||
|
const_cast<Vector *>(this)->MoveToRAM();
|
||||||
|
return BaseClass::at(i);
|
||||||
|
}
|
||||||
|
T &front() {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::front();
|
||||||
|
}
|
||||||
|
const T &front() const {
|
||||||
|
const_cast<Vector *>(this)->MoveToRAM();
|
||||||
|
return BaseClass::front();
|
||||||
|
}
|
||||||
|
T &back() {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::back();
|
||||||
|
}
|
||||||
|
const T &back() const {
|
||||||
|
const_cast<Vector *>(this)->MoveToRAM();
|
||||||
|
return BaseClass::back();
|
||||||
|
}
|
||||||
|
T *data() noexcept {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::data();
|
||||||
|
}
|
||||||
|
const T *data() const noexcept {
|
||||||
|
const_cast<Vector *>(this)->MoveToRAM();
|
||||||
|
return BaseClass::data();
|
||||||
|
}
|
||||||
|
Iterator begin() noexcept {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::begin();
|
||||||
|
}
|
||||||
|
ConstIterator begin() const noexcept {
|
||||||
|
const_cast<Vector *>(this)->MoveToRAM();
|
||||||
|
return BaseClass::begin();
|
||||||
|
}
|
||||||
|
Iterator end() noexcept {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::end();
|
||||||
|
}
|
||||||
|
ConstIterator end() const noexcept {
|
||||||
|
const_cast<Vector *>(this)->MoveToRAM();
|
||||||
|
return BaseClass::end();
|
||||||
|
}
|
||||||
|
auto rbegin() noexcept {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::rbegin();
|
||||||
|
}
|
||||||
|
auto rbegin() const noexcept {
|
||||||
|
const_cast<Vector *>(this)->MoveToRAM();
|
||||||
|
return BaseClass::rbegin();
|
||||||
|
}
|
||||||
|
auto rend() noexcept {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::rend();
|
||||||
|
}
|
||||||
|
auto rend() const noexcept {
|
||||||
|
const_cast<Vector *>(this)->MoveToRAM();
|
||||||
|
return BaseClass::rend();
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const T &x) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
BaseClass::push_back(x);
|
||||||
|
}
|
||||||
|
void push_back(T &&x) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
BaseClass::push_back(std::move(x));
|
||||||
|
}
|
||||||
|
template <typename... Args> reference emplace_back(Args &&...args) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::emplace_back(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
void pop_back() {
|
||||||
|
this->MoveToRAM();
|
||||||
|
BaseClass::pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
iterator emplace(const_iterator pos, Args &&...args) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::emplace(pos, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
iterator insert(const_iterator pos, const T &x) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::insert(pos, x);
|
||||||
|
}
|
||||||
|
iterator insert(const_iterator pos, T &&x) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::insert(pos, std::move(x));
|
||||||
|
}
|
||||||
|
iterator erase(const_iterator pos) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::erase(pos);
|
||||||
|
}
|
||||||
|
iterator erase(const_iterator first, const_iterator last) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
return BaseClass::erase(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(size_t n) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
BaseClass::resize(n);
|
||||||
|
}
|
||||||
|
void resize(size_t n, const T &x) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
BaseClass::resize(n, x);
|
||||||
|
}
|
||||||
|
void reserve(size_t n) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
BaseClass::reserve(n);
|
||||||
|
}
|
||||||
|
void clear() noexcept {
|
||||||
|
this->MoveToRAM();
|
||||||
|
BaseClass::clear();
|
||||||
|
}
|
||||||
|
template <typename InputIt> void assign(InputIt first, InputIt last) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
BaseClass::assign(first, last);
|
||||||
|
}
|
||||||
|
void assign(size_type count, const T &value) {
|
||||||
|
this->MoveToRAM();
|
||||||
|
BaseClass::assign(count, value);
|
||||||
|
}
|
||||||
|
|
||||||
void remove_element(unsigned int index) {
|
void remove_element(unsigned int index) {
|
||||||
|
this->MoveToRAM();
|
||||||
std::swap(this->at(index), this->back());
|
std::swap(this->at(index), this->back());
|
||||||
this->pop_back();
|
this->pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_element(T &t) {
|
void remove_element(T &t) {
|
||||||
|
this->MoveToRAM();
|
||||||
std::swap(t, this->back());
|
std::swap(t, this->back());
|
||||||
this->pop_back();
|
this->pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T> void Vector<T>::PrintSelf(std::ostream &o) {
|
||||||
void Vector<T>::PrintSelf(std::ostream &o)
|
|
||||||
{
|
|
||||||
o << " *** uLib Vector *** \n";
|
o << " *** uLib Vector *** \n";
|
||||||
o << " n. of items = " << this->size() << "\n";
|
o << " n. of items = " << this->size() << "\n";
|
||||||
for (int i = 0; i < this->size(); ++i)
|
for (int i = 0; i < this->size(); ++i)
|
||||||
@@ -98,36 +344,30 @@ std::ofstream & operator << (std::ofstream &o, const Vector<T> &v) {
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T> std::istream &operator>>(std::istream &is, Vector<T> &v) {
|
||||||
template < typename T >
|
|
||||||
std::istream & operator >> (std::istream &is, Vector<T> &v) {
|
|
||||||
T value;
|
T value;
|
||||||
while (is >> value) {
|
while (is >> value) {
|
||||||
if(is.fail()) v.push_back(0);
|
if (is.fail())
|
||||||
else v.push_back( value );
|
v.push_back(0);
|
||||||
|
else
|
||||||
|
v.push_back(value);
|
||||||
}
|
}
|
||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Smart pointer Vector Implementation //
|
// Smart pointer Vector Implementation //
|
||||||
|
|
||||||
|
template <typename T> class SmartVector : public SmartPointer<Vector<T>> {
|
||||||
template <typename T>
|
|
||||||
class SmartVector : public SmartPointer< Vector<T> > {
|
|
||||||
typedef SmartPointer<Vector<T>> Base;
|
typedef SmartPointer<Vector<T>> Base;
|
||||||
public:
|
|
||||||
|
|
||||||
|
public:
|
||||||
SmartVector() : Base(new Vector<T>()) {}
|
SmartVector() : Base(new Vector<T>()) {}
|
||||||
SmartVector(const SmartVector ©) : Base(copy) {}
|
SmartVector(const SmartVector ©) : Base(copy) {}
|
||||||
SmartVector(unsigned int size) : Base(new Vector<T>((int)size)) {}
|
SmartVector(unsigned int size) : Base(new Vector<T>((int)size)) {}
|
||||||
|
|
||||||
virtual ~SmartVector() {}
|
virtual ~SmartVector() {}
|
||||||
|
|
||||||
T& operator[](int p) {
|
T &operator[](int p) { return Base::get()->at(p); }
|
||||||
return Base::get()->at(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap_elements(unsigned int first, unsigned int second) {
|
void swap_elements(unsigned int first, unsigned int second) {
|
||||||
std::swap(Base::get()->at(first), Base::get()->at(second));
|
std::swap(Base::get()->at(first), Base::get()->at(second));
|
||||||
@@ -144,35 +384,25 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------ Utils ------------------------------------------------------------- //
|
// ------ Utils ------------------------------------------------------------- //
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// RIFARE con iteratore !
|
// RIFARE con iteratore !
|
||||||
template <typename _Tp, class _CmpT>
|
template <typename _Tp, class _CmpT>
|
||||||
inline const unsigned long
|
inline unsigned long VectorSplice(const _Tp &_it, const _Tp &_end,
|
||||||
VectorSplice(const _Tp &_it, const _Tp &_end, const float value, _CmpT _comp)
|
const float value, _CmpT _comp) {
|
||||||
{
|
|
||||||
_Tp it = _it;
|
_Tp it = _it;
|
||||||
_Tp end = _end - 1;
|
_Tp end = _end - 1;
|
||||||
for(it; it != end;)
|
for (; it != end;) {
|
||||||
{
|
if (_comp(*it, value))
|
||||||
if (_comp(*it,value)) ++it;
|
++it;
|
||||||
else if(_comp(*end,value)) std::swap(*it,*end--);
|
else if (_comp(*end, value))
|
||||||
else --end;
|
std::swap(*it, *end--);
|
||||||
|
else
|
||||||
|
--end;
|
||||||
}
|
}
|
||||||
return it - _it;
|
return it - _it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace uLib
|
||||||
|
|
||||||
} // uLib
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // VECTOR_H
|
#endif // VECTOR_H
|
||||||
|
|||||||
31
src/Core/test_meta_allocator.cpp
Normal file
31
src/Core/test_meta_allocator.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include <Core/Vector.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
uLib::Vector<int> v;
|
||||||
|
v.push_back(1);
|
||||||
|
v.push_back(2);
|
||||||
|
v.push_back(3);
|
||||||
|
|
||||||
|
std::cout << "RAM Vector elements: ";
|
||||||
|
for (int i = 0; i < v.size(); ++i) {
|
||||||
|
std::cout << v[i] << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
#ifdef USE_CUDA
|
||||||
|
std::cout << "Moving to VRAM..." << std::endl;
|
||||||
|
v.MoveToVRAM();
|
||||||
|
int *vram_ptr = v.GetVRAMData();
|
||||||
|
if (vram_ptr) {
|
||||||
|
std::cout << "Successfully got VRAM pointer!" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Failed to get VRAM pointer!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Moving back to RAM..." << std::endl;
|
||||||
|
v.MoveToRAM();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ set( TESTS
|
|||||||
TypeIntrospectionTraversal
|
TypeIntrospectionTraversal
|
||||||
OptionsTest
|
OptionsTest
|
||||||
PingPongTest
|
PingPongTest
|
||||||
|
VectorMetaAllocatorTest
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBRARIES
|
set(LIBRARIES
|
||||||
|
|||||||
71
src/Core/testing/VectorMetaAllocatorTest.cpp
Normal file
71
src/Core/testing/VectorMetaAllocatorTest.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
#include "testing-prototype.h"
|
||||||
|
#include <Core/Vector.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
BEGIN_TESTING(VectorMetaAllocator);
|
||||||
|
|
||||||
|
uLib::Vector<int> v;
|
||||||
|
std::cout << "Pushing elements...\n";
|
||||||
|
v << 1, 2, 3, 4, 5;
|
||||||
|
|
||||||
|
std::cout << "Initial RAM contents: ";
|
||||||
|
for (size_t i = 0; i < v.size(); ++i) {
|
||||||
|
std::cout << v[i] << " ";
|
||||||
|
if (v[i] != (int)(i + 1)) {
|
||||||
|
std::cout << "\nError: Value mismatch at index " << i << "\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
#ifdef USE_CUDA
|
||||||
|
std::cout << "Moving to VRAM...\n";
|
||||||
|
v.MoveToVRAM();
|
||||||
|
|
||||||
|
int *vram_ptr = v.GetVRAMData();
|
||||||
|
if (vram_ptr) {
|
||||||
|
std::cout << "Successfully obtained VRAM pointer: " << vram_ptr << "\n";
|
||||||
|
} else {
|
||||||
|
std::cout << "Error: Failed to obtain VRAM pointer!\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Moving back to RAM...\n";
|
||||||
|
v.MoveToRAM();
|
||||||
|
|
||||||
|
std::cout << "RAM contents after VRAM trip: ";
|
||||||
|
for (size_t i = 0; i < v.size(); ++i) {
|
||||||
|
std::cout << v[i] << " ";
|
||||||
|
if (v[i] != (int)(i + 1)) {
|
||||||
|
std::cout << "\nError: Data corrupted after RAM->VRAM->RAM trip at index "
|
||||||
|
<< i << "\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
#else
|
||||||
|
std::cout << "USE_CUDA not defined, skipping VRAM tests.\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::cout << "Scaling vector...\n";
|
||||||
|
for (size_t i = 0; i < v.size(); ++i)
|
||||||
|
v[i] *= 10;
|
||||||
|
|
||||||
|
std::cout << "Final contents: ";
|
||||||
|
for (size_t i = 0; i < v.size(); ++i)
|
||||||
|
std::cout << v[i] << " ";
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
END_TESTING;
|
||||||
|
}
|
||||||
@@ -23,53 +23,40 @@
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <Core/Vector.h>
|
|
||||||
#include "testing-prototype.h"
|
#include "testing-prototype.h"
|
||||||
|
#include <Core/Vector.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
template < typename T >
|
template <typename T> struct __Cmp {
|
||||||
struct __Cmp {
|
bool operator()(const T &data, const float value) { return data <= value; }
|
||||||
bool operator()(const T &data, const float value) {
|
|
||||||
return data <= value;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename _Tp, typename _CmpT>
|
template <typename _Tp, typename _CmpT>
|
||||||
inline const unsigned long
|
inline const unsigned long VectorSplice(const _Tp &_it, const _Tp &_end,
|
||||||
VectorSplice(const _Tp &_it, const _Tp &_end, const float value, _CmpT _comp)
|
const float value, _CmpT _comp) {
|
||||||
{
|
|
||||||
|
|
||||||
_Tp it = _it;
|
_Tp it = _it;
|
||||||
_Tp end = _end - 1;
|
_Tp end = _end - 1;
|
||||||
for(it; it != end; )
|
for (it; it != end;) {
|
||||||
{
|
if (_comp(*it, value))
|
||||||
if ( _comp(*it, value) ) it++;
|
it++;
|
||||||
else if( _comp(*end, value) )
|
else if (_comp(*end, value)) {
|
||||||
{
|
|
||||||
std::swap(*it, *end--);
|
std::swap(*it, *end--);
|
||||||
}
|
} else
|
||||||
else --end;
|
--end;
|
||||||
}
|
}
|
||||||
return it - _it;
|
return it - _it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
int main()
|
|
||||||
{
|
|
||||||
BEGIN_TESTING(Vector);
|
BEGIN_TESTING(Vector);
|
||||||
|
|
||||||
uLib::Vector<float> v;
|
uLib::Vector<float> v;
|
||||||
v << 5,4,3,2,6,1,2,3,65,7,32,23,4,3,45,4,34,3,4,4,3,3,4,2,2,3;
|
v << 5, 4, 3, 2, 6, 1, 2, 3, 65, 7, 32, 23, 4, 3, 45, 4, 34, 3, 4, 4, 3, 3, 4,
|
||||||
|
2, 2, 3;
|
||||||
|
|
||||||
|
int id = ::VectorSplice(v.begin(), v.end(), 3, __Cmp<float>());
|
||||||
|
|
||||||
int id = VectorSplice(v.begin(),v.end(),3,__Cmp<float>());
|
|
||||||
|
|
||||||
std::cout << "id: " << id << "\n";
|
std::cout << "id: " << id << "\n";
|
||||||
std::cout << "vector: ";
|
std::cout << "vector: ";
|
||||||
@@ -78,7 +65,5 @@ int main()
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
// std::sort(v.begin(),v.end(),LT<float>());
|
// std::sort(v.begin(),v.end(),LT<float>());
|
||||||
|
|
||||||
|
|
||||||
END_TESTING;
|
END_TESTING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Math/DataAllocator.h"
|
#include <Core/DataAllocator.h>
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
#ifndef VOXRAYTRACER_H
|
#ifndef VOXRAYTRACER_H
|
||||||
#define VOXRAYTRACER_H
|
#define VOXRAYTRACER_H
|
||||||
|
|
||||||
#include "Math/DataAllocator.h"
|
#include <Core/DataAllocator.h>
|
||||||
|
#include <Core/Vector.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -56,9 +57,9 @@ public:
|
|||||||
|
|
||||||
void AppendRay(const RayData &in);
|
void AppendRay(const RayData &in);
|
||||||
|
|
||||||
inline DataAllocator<Element> &Data() { return this->m_Data; }
|
inline uLib::Vector<Element> &Data() { return this->m_Data; }
|
||||||
|
|
||||||
inline const DataAllocator<Element> &Data() const { return this->m_Data; }
|
inline const uLib::Vector<Element> &Data() const { return this->m_Data; }
|
||||||
|
|
||||||
inline size_t Count() const { return this->m_Count; }
|
inline size_t Count() const { return this->m_Count; }
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ public:
|
|||||||
void PrintSelf(std::ostream &o);
|
void PrintSelf(std::ostream &o);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DataAllocator<Element> m_Data;
|
uLib::Vector<Element> m_Data;
|
||||||
Scalarf m_TotalLength;
|
Scalarf m_TotalLength;
|
||||||
size_t m_Count;
|
size_t m_Count;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user