-
Notifications
You must be signed in to change notification settings - Fork 122
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use connected lists for tape data structure
Instead of a single list use mutliple connected lists to store elements. This allows to dynamically increase the size of tape without the need of relocating elements.
- Loading branch information
1 parent
8749404
commit 8e1575b
Showing
5 changed files
with
146 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
#ifndef CLAD_DIFFERENTIATOR_NEWTAPE_H | ||
#define CLAD_DIFFERENTIATOR_NEWTAPE_H | ||
|
||
#include <cassert> | ||
#include <cstdio> | ||
#include <new> | ||
#include <type_traits> | ||
#include <utility> | ||
|
||
#include "clad/Differentiator/CladConfig.h" | ||
|
||
namespace clad { | ||
|
||
template <typename T> class Block { | ||
public: | ||
T* data; | ||
Block<T>* next; | ||
Block<T>* prev; | ||
std::size_t capacity; | ||
using pointer = T*; | ||
using iterator = pointer; | ||
|
||
CUDA_HOST_DEVICE Block(std::size_t& capacity) | ||
: next(nullptr), prev(nullptr), capacity(capacity), | ||
data(allocateRawStorage(capacity)) {} | ||
|
||
CUDA_HOST_DEVICE ~Block() { | ||
destroy(block_begin(), block_end()); | ||
::operator delete( | ||
const_cast<void*>(static_cast<const volatile void*>(data))); | ||
} | ||
Block(const Block& other) = delete; | ||
Block& operator=(const Block& other) = delete; | ||
|
||
Block(Block&& other) = delete; | ||
Block& operator=(const Block&& other) = delete; | ||
|
||
CUDA_HOST_DEVICE iterator block_begin() { return data; } | ||
|
||
CUDA_HOST_DEVICE iterator block_end() { return data + capacity; } | ||
|
||
template <typename It> using value_type_of = decltype(*std::declval<It>()); | ||
|
||
CUDA_HOST_DEVICE T* allocateRawStorage(std::size_t capacity) { | ||
#ifdef __CUDACC__ | ||
return static_cast<T*>(::operator new(capacity * sizeof(T), std::nothrow)); | ||
#else | ||
return static_cast<T*>(::operator new(capacity * sizeof(T), std::nothrow)); | ||
#endif | ||
} | ||
|
||
template <typename It> | ||
static typename std::enable_if< | ||
!std::is_trivially_destructible<value_type_of<It>>::value>::type | ||
destroy(It B, It E) { | ||
for (It I = E - 1; I >= B; --I) | ||
I->~value_type_of<It>(); | ||
} | ||
|
||
template <typename It> | ||
static typename std::enable_if< | ||
std::is_trivially_destructible<value_type_of<It>>::value>::type | ||
CUDA_HOST_DEVICE | ||
destroy(It B, It E) {} | ||
}; | ||
|
||
template <typename T> class new_tape_impl { | ||
Block<T>* m_cur_block = nullptr; | ||
std::size_t m_capacity = 128; | ||
std::size_t m_size = 0; | ||
using pointer = T*; | ||
using reference = T&; | ||
|
||
using iterator = pointer; | ||
|
||
public: | ||
new_tape_impl() = default; | ||
|
||
~new_tape_impl() { | ||
while (m_cur_block) { | ||
Block<T>* prev_block = m_cur_block->prev; | ||
delete m_cur_block; | ||
m_cur_block = prev_block; | ||
} | ||
} | ||
|
||
new_tape_impl(new_tape_impl& other) = delete; | ||
new_tape_impl operator=(new_tape_impl& other) = delete; | ||
|
||
new_tape_impl(new_tape_impl&& other) = delete; | ||
new_tape_impl& operator=(new_tape_impl&& other) = delete; | ||
|
||
template <typename... ArgsT> | ||
|
||
CUDA_HOST_DEVICE void emplace_back(ArgsT&&... args) { | ||
if (!m_cur_block || m_size >= m_capacity) { | ||
Block<T>* prev_block = m_cur_block; | ||
m_cur_block = new Block<T>(m_capacity); | ||
if (prev_block) { | ||
prev_block->next = m_cur_block; | ||
m_cur_block->prev = prev_block; | ||
} | ||
m_size = 0; | ||
} | ||
m_size += 1; | ||
::new (const_cast<void*>(static_cast<const volatile void*>(end()))) | ||
T(std::forward<ArgsT>(args)...); | ||
} | ||
|
||
[[nodiscard]] CUDA_HOST_DEVICE std::size_t size() const { return m_size; } | ||
|
||
CUDA_HOST_DEVICE iterator end() { return m_cur_block->data + (m_size - 1); } | ||
|
||
CUDA_HOST_DEVICE reference back() { | ||
assert(m_size || m_cur_block->prev); | ||
return *end(); | ||
} | ||
|
||
CUDA_HOST_DEVICE void pop_back() { | ||
assert(m_size || m_cur_block->prev); | ||
end()->~T(); | ||
m_size -= 1; | ||
if (m_size == 0) { | ||
Block<T>* temp = m_cur_block; | ||
m_cur_block = m_cur_block->prev; | ||
temp->~Block<T>(); | ||
m_size = m_capacity; | ||
} | ||
} | ||
}; | ||
} // namespace clad | ||
|
||
#endif // CLAD_DIFFERENTIATOR_NEWTAPE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters