From f8b8c92b407d5ebeee4d6b015f93b547abf25527 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Mon, 3 Jun 2024 11:46:19 -0700 Subject: [PATCH] ILP firstGeq WIP --- VersionedMap.cpp | 130 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 92 insertions(+), 38 deletions(-) diff --git a/VersionedMap.cpp b/VersionedMap.cpp index bc5657e..dffa09c 100644 --- a/VersionedMap.cpp +++ b/VersionedMap.cpp @@ -1229,53 +1229,107 @@ bool geq(const VersionedMap::Iterator::VersionedMutation &m, void VersionedMap::Impl::firstGeq(const weaselab::VersionedMap::Key *key, const int64_t *version, Iterator *iterator, int count) const { - // TODO ILP! - auto handle = roots.getThreadSafeHandle(); - for (int i = 0; i < count; ++i) { - uint32_t root; - if (iterator[i].impl != nullptr) { - root = iterator[i].impl->version == version[i] - ? iterator[i].impl->finger.root() - : handle.rootForVersion(version[i]); - iterator[i].impl->~Impl(); - new (iterator[i].impl) Iterator::Impl(); - } else { - root = handle.rootForVersion(version[i]); - iterator[i].impl = - new (safe_malloc(sizeof(Iterator::Impl))) Iterator::Impl(); - } - Finger &finger = iterator[i].impl->finger; - search(key[i], root, version[i], finger); + struct StepwiseFirstGeq { - if (finger.searchPathSize() > 0 && finger.backNode() == 0) { - move(finger, version[i]); - if (finger.searchPathSize() > 0) { - assert(finger.backNode() != 0); + const VersionedMap::Impl *map; + const weaselab::VersionedMap::Key *key; + const int64_t *version; + weaselab::VersionedMap::Iterator *iterator; + uint32_t node; + + void begin(RootSet::ThreadSafeHandle handle) { + if (iterator->impl != nullptr) { + node = iterator->impl->version == *version + ? iterator->impl->finger.root() + : handle.rootForVersion(*version); + iterator->impl->~Impl(); + new (iterator->impl) Iterator::Impl(); + } else { + node = handle.rootForVersion(*version); + iterator->impl = + new (safe_malloc(sizeof(Iterator::Impl))) Iterator::Impl(); } } - iterator[i].impl->version = version[i]; - iterator[i].impl->map = this; + bool step() { + Finger &finger = iterator->impl->finger; + map->search(*key, node, *version, finger); + return true; + } - const Entry *prev = nullptr; - for (;;) { - if (finger.searchPathSize() == 0) { - break; - } else { - materializeMutations(iterator[i].impl, prev, nullptr); - for (int j = 0; j < iterator[i].impl->mutationCount; ++j) { - if (geq(iterator[i].impl->mutations[j], key[i])) { - iterator[i].impl->mutationIndex = j; - goto loopEnd; - } + void end() { + Finger &finger = iterator->impl->finger; + if (finger.searchPathSize() > 0 && finger.backNode() == 0) { + map->move(finger, *version); + if (finger.searchPathSize() > 0) { + assert(finger.backNode() != 0); } } - prev = iterator[i].impl->map->mm.base[finger.backNode()].entry; - iterator[i].impl->map->move( - finger, iterator[i].impl->version); + + iterator->impl->version = *version; + iterator->impl->map = map; + + const Entry *prev = nullptr; + for (;;) { + if (finger.searchPathSize() == 0) { + break; + } else { + materializeMutations(iterator->impl, prev, nullptr); + for (int j = 0; j < iterator->impl->mutationCount; ++j) { + if (geq(iterator->impl->mutations[j], *key)) { + iterator->impl->mutationIndex = j; + goto loopEnd; + } + } + } + prev = iterator->impl->map->mm.base[finger.backNode()].entry; + iterator->impl->map->move( + finger, iterator->impl->version); + } + loopEnd:; } - loopEnd:; + }; + + // Use stack allocation for small count + Arena arena; + constexpr int kStackAllocThreshold = 2; + StepwiseFirstGeq stepwiseStackAlloc[kStackAllocThreshold]; + int nextJobStackAllocation[kStackAllocThreshold]; + StepwiseFirstGeq *stepwise; + int *nextJob; + if (count <= kStackAllocThreshold) { + stepwise = stepwiseStackAlloc; + nextJob = nextJobStackAllocation; + } else { + stepwise = new (arena) StepwiseFirstGeq[count]; + nextJob = new (arena) int[count]; + } + + auto handle = roots.getThreadSafeHandle(); + for (int i = 0; i < count; ++i) { + stepwise[i].map = this; + stepwise[i].key = &key[i]; + stepwise[i].version = &version[i]; + stepwise[i].iterator = &iterator[i]; + stepwise[i].begin(handle); + nextJob[i] = i + 1; + } + nextJob[count - 1] = 0; + int prevJob = count - 1; + int job = 0; + + for (;;) { + if (stepwise[job].step()) { + stepwise[job].end(); + if (job == prevJob) { + break; + } + nextJob[prevJob] = nextJob[job]; + job = prevJob; + } + prevJob = job; + job = nextJob[job]; } }