Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2fb45c3
Memory mapped file API (mapped_file library)
JATothrim Jul 28, 2023
f37d0f1
- fixup region::remap() mremap case not saving the correct size.
JATothrim Jul 30, 2023
48a71f9
fixup missing const in struct_region and array_region
JATothrim Jul 30, 2023
6a637a6
libmappedfile: implement oversized mapped region
JATothrim Jul 31, 2023
27d56d0
libmappedfile: Provide writeAt() readAt() API
JATothrim Aug 2, 2023
d5ca48b
libmappedfile: Misc changes
JATothrim Aug 2, 2023
fbcd80a
libmapped_file: Make region moveable
JATothrim Aug 9, 2023
a8b5e1f
libmappedfile: Implement region::window()
JATothrim Aug 10, 2023
aeac726
libmapped_file: Tune the memory mapping a bit
JATothrim Aug 10, 2023
a6702de
libmappedfile: comment fixups
JATothrim Aug 11, 2023
ac6a200
libmappedfile: Locking and discard work
JATothrim Aug 12, 2023
0f3a340
Do const safety pass
JATothrim Jul 30, 2023
dc47afa
Close the `friend class Workset` trick.
JATothrim Jul 30, 2023
0b27a88
Update newCache to use libmappedfile
JATothrim Jul 30, 2023
1e60971
fixup tests not compiling.
JATothrim Aug 13, 2023
8a8e850
Make DEBUG_PRINT less noisy
JATothrim Aug 2, 2023
3ea29d1
Hack Cube struct into 8-bytes
JATothrim Aug 10, 2023
0c0b1da
Hashy const qualifiers.
JATothrim Aug 11, 2023
759be1a
cubes: Refactor thread scheduling
JATothrim Aug 11, 2023
243fb3e
CacheWriter class
JATothrim Aug 13, 2023
31618c4
CacheWriter: Parallel serialization
JATothrim Aug 14, 2023
25b9694
Remove include/cache.hpp src/cache.cpp
JATothrim Aug 14, 2023
7c68374
CacheWriter: Fix-up synchronization
JATothrim Aug 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ macro(ConfigureTarget Target)
)
endmacro()

add_library(mapped_file STATIC "libraries/mapped_file.cpp")
ConfigureTarget(mapped_file)

# Source files
add_library(CubeObjs OBJECT
"src/cubes.cpp"
"src/cache.cpp"
"src/rotations.cpp"
"src/newCache.cpp"
)
Expand All @@ -50,6 +52,7 @@ ConfigureTarget(CubeObjs)
# Build main program
add_executable(${PROJECT_NAME} "program.cpp" $<TARGET_OBJECTS:CubeObjs>)
target_link_libraries(${PROJECT_NAME} pthread)
target_link_libraries(${PROJECT_NAME} mapped_file)
ConfigureTarget(${PROJECT_NAME})

# Optionally build tests
Expand Down
35 changes: 0 additions & 35 deletions cpp/include/cache.hpp

This file was deleted.

81 changes: 58 additions & 23 deletions cpp/include/cube.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <memory>
#include <unordered_set>
#include <vector>
#include <atomic>

#include "utils.hpp"

Expand Down Expand Up @@ -45,20 +46,47 @@ using XYZSet = std::unordered_set<XYZ, HashXYZ, std::equal_to<XYZ>>;

struct Cube {
private:
struct {
uint8_t is_shared : 1;
uint8_t size : 7; // MAX 127
} bits;
XYZ *array = nullptr;

static_assert(sizeof(bits) == sizeof(uint8_t));
// cube memory is stored two ways:
// normal, new'd buffer: is_shared == false
// shared, external memory: is_shared == true

struct bits_t {
uint64_t is_shared : 1;
uint64_t size : 7; // MAX 127
uint64_t addr : 56; // low 56-bits of memory address.
};
// fields
bits_t fields;

static_assert(sizeof(bits_t) == sizeof(void*));
// extract the pointer from bits_t
static XYZ *get(bits_t key) {
// pointer bit-hacking:
uint64_t addr = key.addr;
return reinterpret_cast<XYZ *>(addr);
}

static bits_t put(bool is_shared, int size, XYZ *addr) {
// mask off top byte from the memory address to fit it into bits_t::addr
// on x86-64 it is not used by the hardware (yet).
// This hack actually saves 8 bytes because previously
// the uint8_t caused padding to 16 bytes.
// @note if we get segfaults dereferencing get(fields)
// then this is the problem and this hack must be undone.
uint64_t tmp = reinterpret_cast<uint64_t>((void *)addr);
tmp &= 0xffffffffffffff;
bits_t bits;
bits.addr = tmp;
bits.is_shared = is_shared;
bits.size = size;
return bits;
}
public:
// Empty cube
Cube() : bits{0, 0} {}
Cube() : fields{put(0, 0, nullptr)} {}

// Cube with N capacity
explicit Cube(uint8_t N) : bits{0, N}, array(new XYZ[bits.size]) {}
explicit Cube(uint8_t N) : fields{put(0,N, new XYZ[N])} {}

// Construct from pieces
Cube(std::initializer_list<XYZ> il) : Cube(il.size()) { std::copy(il.begin(), il.end(), begin()); }
Expand All @@ -69,20 +97,23 @@ struct Cube {
// Construct from external source.
// Cube shares this the memory until modified.
// Caller guarantees the memory given will live longer than *this
Cube(XYZ *start, uint8_t n) : bits{1, n}, array(start) {}
Cube(const XYZ *start, uint8_t n) : fields{put(1,n,const_cast<XYZ*>(start))} {}

// Copy ctor.
Cube(const Cube &copy) : Cube(copy.size()) { std::copy(copy.begin(), copy.end(), begin()); }

~Cube() {
bits_t bits = fields;
if (!bits.is_shared) {
delete[] array;
delete[] get(bits);
}
}
friend void swap(Cube &a, Cube &b) {
using std::swap;
swap(a.array, b.array);
swap(a.bits, b.bits);
bits_t abits = a.fields;
bits_t bbits = b.fields;
a.fields = bbits;
b.fields = abits;
}

Cube(Cube &&mv) : Cube() { swap(*this, mv); }
Expand All @@ -98,19 +129,15 @@ struct Cube {
return *this;
}

size_t size() const { return bits.size; }
size_t size() const { return fields.size; }

XYZ *data() {
if (bits.is_shared) {
// lift to RAM: this should never happen really.
Cube tmp(array, bits.size);
swap(*this, tmp);
std::printf("Bad use of Cube\n");
}
return array;
}
return get(fields);
}

const XYZ *data() const { return array; }
const XYZ *data() const {
return get(fields);
}

XYZ *begin() { return data(); }

Expand Down Expand Up @@ -138,8 +165,16 @@ struct Cube {
void print() const {
for (auto &p : *this) std::printf(" (%2d %2d %2d)\n\r", p.x(), p.y(), p.z());
}

/**
* Copy cube data into destination buffer.
*/
void copyout(int num, XYZ* dest) const {
std::copy_n(begin(), num, dest);
}
};

static_assert(sizeof(Cube) == 8, "Unexpected sizeof(Cube) for Cube");
static_assert(std::is_move_assignable_v<Cube>, "Cube must be moveable");
static_assert(std::is_swappable_v<Cube>, "Cube must swappable");

Expand Down
20 changes: 12 additions & 8 deletions cpp/include/hashes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,24 @@ using CubeSet = std::unordered_set<Cube, HashCube, std::equal_to<Cube>>;
struct Hashy {
struct Subsubhashy {
CubeSet set;
std::shared_mutex set_mutex;
mutable std::shared_mutex set_mutex;

template <typename CubeT>
void insert(CubeT &&c) {
std::lock_guard lock(set_mutex);
set.emplace(std::forward<CubeT>(c));
}

bool contains(const Cube &c) {
bool contains(const Cube &c) const {
std::shared_lock lock(set_mutex);
return set.count(c);
auto itr = set.find(c);
if(itr != set.end()) {
return true;
}
return false;
}

auto size() {
auto size() const {
std::shared_lock lock(set_mutex);
return set.size();
}
Expand All @@ -59,7 +63,7 @@ struct Hashy {
// printf("new size %ld\n\r", byshape[shape].size());
}

auto size() {
auto size() const {
size_t sum = 0;
for (auto &set : byhash) {
auto part = set.size();
Expand Down Expand Up @@ -95,12 +99,12 @@ struct Hashy {
set.insert(std::forward<CubeT>(c));
}

auto size() {
auto size() const {
size_t sum = 0;
DEBUG_PRINTF("%ld maps by shape\n\r", byshape.size());
DEBUG1_PRINTF("%ld maps by shape\n\r", byshape.size());
for (auto &set : byshape) {
auto part = set.second.size();
DEBUG_PRINTF("bucket [%2d %2d %2d]: %ld\n", set.first.x(), set.first.y(), set.first.z(), part);
DEBUG1_PRINTF("bucket [%2d %2d %2d]: %ld\n", set.first.x(), set.first.y(), set.first.z(), part);
sum += part;
}
return sum;
Expand Down
Loading