From 22afd2c41777f68dfbc26af273da7e7c01319b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Mu=C5=82a?= Date: Sun, 18 Feb 2018 17:13:54 +0100 Subject: [PATCH] Another sequantial variant --- .../SequentialAndZeroTracking.h | 66 +++++++++++++++++++ parallel-and-bitmaps/bitvector.h | 6 ++ parallel-and-bitmaps/main.cpp | 10 ++- 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 parallel-and-bitmaps/SequentialAndZeroTracking.h diff --git a/parallel-and-bitmaps/SequentialAndZeroTracking.h b/parallel-and-bitmaps/SequentialAndZeroTracking.h new file mode 100644 index 0000000..db8cccc --- /dev/null +++ b/parallel-and-bitmaps/SequentialAndZeroTracking.h @@ -0,0 +1,66 @@ +#pragma once + +#include +#include "MultipleAndInterface.h" + +class SequentialAndZeroTracking: public MultipleAndInterface { + +protected: + std::vector input; + std::vector zero; + const size_t block_size = 64; + +public: + SequentialAndZeroTracking(const std::vector& input_) + : input(input_) { + + assert(input.size() >= 2); + + const size_t n = (input[0]->n + block_size - 1) / block_size; + zero.resize(n); + } + + virtual std::unique_ptr calculate() override { + + bitvector* bv = new bitvector(*input[0]); + +#if 0 +# define TRACE(msg, ...) printf(msg, __VA_ARGS__) +#else +# define TRACE(msg, ...) +#endif + + size_t zero_blocks = 0; + for (size_t i=1; i < input.size(); i++) { + TRACE("bitmap %lu of %lu\n", i, input.size() - 1); + for (size_t j=0; j < zero.size(); j++) { + if (zero[j]) { + continue; // skip zero block + } + + const size_t start = j * block_size; + const size_t end = std::min(start + block_size, bv->n); + + uint64_t nonzero = 0; + for (size_t p=start; p < end; p++) { + bv->data[p] &= input[i]->data[p]; + nonzero |= bv->data[p]; + } + + if (nonzero == 0) { + // the block is zero, skip in the future + TRACE("\tblock %lu will be skip\n", j); + zero[j] = 1; + zero_blocks += 1; + } + } + + if (zero_blocks == zero.size()) { + TRACE("early exit after processing bitmap %lu\n", i); + break; // all blocks are zero + } + } + + return std::unique_ptr(bv); + } +}; diff --git a/parallel-and-bitmaps/bitvector.h b/parallel-and-bitmaps/bitvector.h index 29d3fda..036a22d 100644 --- a/parallel-and-bitmaps/bitvector.h +++ b/parallel-and-bitmaps/bitvector.h @@ -2,6 +2,7 @@ #include #include +#include #include class bitvector { @@ -16,6 +17,11 @@ class bitvector { data = new uint64_t[n]; } + bitvector(const bitvector& bv) : bitvector(bv.n) { + + memcpy(data, bv.data, n * sizeof(uint64_t)); + } + ~bitvector() { delete[] data; } diff --git a/parallel-and-bitmaps/main.cpp b/parallel-and-bitmaps/main.cpp index 09a3da4..ce97aa3 100644 --- a/parallel-and-bitmaps/main.cpp +++ b/parallel-and-bitmaps/main.cpp @@ -1,6 +1,7 @@ #include #include "SequentialAnd.h" +#include "SequentialAndZeroTracking.h" #include "ParallelAndNaive.h" #include "ParallelAndSplit.h" @@ -12,7 +13,7 @@ void test(const char* info, MultipleAndInterface& ma, const std::vector= 2); - printf("%-20s (%lu bitmaps): ", info, input.size()); + printf("%-30s (%lu bitmaps): ", info, input.size()); fflush(stdout); const auto t1 = Clock::now(); @@ -20,12 +21,12 @@ void test(const char* info, MultipleAndInterface& ma, const std::vector(t2 - t1).count(); - printf("%luus [cardinality=%lu]\n", t_us, res->cardinality()); + printf("%10luus [cardinality=%lu]\n", t_us, res->cardinality()); } int main() { - const size_t bitmap_size = 2000000; + const size_t bitmap_size = 1000000; const size_t count = 100; std::vector input; @@ -40,6 +41,9 @@ int main() { SequentialAnd seq(input); test("SequentialAnd", seq, input); + SequentialAndZeroTracking seq2(input); + test("SequentialAndZeroTracking", seq2, input); + ParallelAndNaive par1(input, 4); test("ParallelAndNaive", par1, input);