ILP firstGeq WIP
This commit is contained in:
130
VersionedMap.cpp
130
VersionedMap.cpp
@@ -1229,53 +1229,107 @@ bool geq(const VersionedMap::Iterator::VersionedMutation &m,
|
|||||||
void VersionedMap::Impl::firstGeq(const weaselab::VersionedMap::Key *key,
|
void VersionedMap::Impl::firstGeq(const weaselab::VersionedMap::Key *key,
|
||||||
const int64_t *version, Iterator *iterator,
|
const int64_t *version, Iterator *iterator,
|
||||||
int count) const {
|
int count) const {
|
||||||
// TODO ILP!
|
|
||||||
auto handle = roots.getThreadSafeHandle();
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
|
|
||||||
uint32_t root;
|
struct StepwiseFirstGeq {
|
||||||
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<std::memory_order_acquire>(key[i], root, version[i], finger);
|
|
||||||
|
|
||||||
if (finger.searchPathSize() > 0 && finger.backNode() == 0) {
|
const VersionedMap::Impl *map;
|
||||||
move<std::memory_order_acquire, true>(finger, version[i]);
|
const weaselab::VersionedMap::Key *key;
|
||||||
if (finger.searchPathSize() > 0) {
|
const int64_t *version;
|
||||||
assert(finger.backNode() != 0);
|
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];
|
bool step() {
|
||||||
iterator[i].impl->map = this;
|
Finger &finger = iterator->impl->finger;
|
||||||
|
map->search<std::memory_order_acquire>(*key, node, *version, finger);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const Entry *prev = nullptr;
|
void end() {
|
||||||
for (;;) {
|
Finger &finger = iterator->impl->finger;
|
||||||
if (finger.searchPathSize() == 0) {
|
if (finger.searchPathSize() > 0 && finger.backNode() == 0) {
|
||||||
break;
|
map->move<std::memory_order_acquire, true>(finger, *version);
|
||||||
} else {
|
if (finger.searchPathSize() > 0) {
|
||||||
materializeMutations(iterator[i].impl, prev, nullptr);
|
assert(finger.backNode() != 0);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prev = iterator[i].impl->map->mm.base[finger.backNode()].entry;
|
|
||||||
iterator[i].impl->map->move<std::memory_order_acquire, true>(
|
iterator->impl->version = *version;
|
||||||
finger, iterator[i].impl->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<std::memory_order_acquire, true>(
|
||||||
|
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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user