Browse Source

perf: AllCases module

master
Dnomd343 2 years ago
parent
commit
cc521f2331
  1. 56
      src/all_cases/all_cases.cc
  2. 15
      src/all_cases/all_cases.h
  3. 4
      src/all_cases/basic_ranges.cc
  4. 3
      src/all_cases/basic_ranges.h
  5. 11
      src/main.cc

56
src/all_cases/all_cases.cc

@ -1,47 +1,51 @@
#include "common.h"
#include "all_cases.h"
std::mutex AllCases::all_cases_building;
bool AllCases::all_cases_available = false;
std::vector<uint32_t> AllCases::all_cases[];
std::mutex AllCases::building;
bool AllCases::available = false;
std::vector<uint32_t> AllCases::data[];
AllCases::Status AllCases::status() { // get all cases status
if (all_cases_available) {
if (AllCases::available) {
return AVAILABLE; // all cases already built
}
if (!all_cases_building.try_lock()) { // fail to lock mutex -> another thread working
return BUILDING;
if (!AllCases::building.try_lock()) { // fail to lock mutex
return BUILDING; // another thread working
}
all_cases_building.unlock(); // release mutex
AllCases::building.unlock(); // release mutex
return NO_INIT;
}
const std::vector<uint32_t> (*AllCases::fetch())[16] { // get const ptr of all cases
if (status() != AllCases::AVAILABLE) {
const std::vector<uint32_t> (*AllCases::fetch())[16] { // get all cases content
if (status() != AVAILABLE) {
AllCases::build(); // all cases initialize
}
return &all_cases; // return ptr
return &AllCases::data; // return const ptr
}
void AllCases::build() { // build all cases
if (AllCases::all_cases_available) {
return; // all cases already built
void AllCases::build() { // ensure that all cases available
if (!AllCases::available) {
if (AllCases::building.try_lock()) { // mutex lock success
build_data(); // start build process
AllCases::available = true; // set available flag
} else {
AllCases::building.lock(); // blocking waiting
}
AllCases::building.unlock();
}
if (AllCases::all_cases_building.try_lock()) { // lock success -> start building
}
void AllCases::build_data() { // find all cases
for (uint32_t head = 0; head < 16; ++head) { // address of 2x2 block
if ((head & 0b11) == 0b11) {
continue; // invalid 2x2 address
}
/// head -> 0/1/2 / 4/5/6 / 8/9/10 / 12/13/14
for (uint32_t head = 0; head < 16; ++head) { // address of 2x2 block
if ((head & 0b11) == 0b11) {
continue; // invalid 2x2 address
}
for (uint32_t const &range : *BasicRanges::fetch()) { // check base on 2x2 address and range
if (Common::check_case(head, range)) {
all_cases[head].emplace_back(Common::range_reverse(range)); // found valid case
}
data[head].reserve(ALL_CASES_SIZE[head]); // memory pre-allocated
for (auto const &range : *BasicRanges::fetch()) { // check base on 2x2 address and range
if (Common::check_case(head, range)) {
data[head].emplace_back(Common::range_reverse(range)); // found valid case
}
}
AllCases::all_cases_available = true; // set available flag
} else { // another thread building
AllCases::all_cases_building.lock(); // blocking waiting
}
AllCases::all_cases_building.unlock();
}

15
src/all_cases/all_cases.h

@ -5,6 +5,13 @@
#include <cstdint>
#include "basic_ranges.h"
const uint32_t ALL_CASES_SIZE[16] = {
2942906, 2260392, 2942906, 0,
2322050, 1876945, 2322050, 0,
2322050, 1876945, 2322050, 0,
2942906, 2260392, 2942906, 0,
};
class AllCases : public BasicRanges {
public:
static void build();
@ -12,7 +19,9 @@ public:
static const std::vector<uint32_t> (*fetch())[16];
private:
static bool all_cases_available;
static std::mutex all_cases_building;
static std::vector<uint32_t> all_cases[16];
static bool available;
static std::mutex building;
static std::vector<uint32_t> data[16];
static void build_data();
};

4
src/all_cases/basic_ranges.cc

@ -26,7 +26,7 @@ BasicRanges::Status BasicRanges::status() { // get basic ranges status
return NO_INIT;
}
const std::vector<uint32_t>* BasicRanges::fetch() { // get const ptr of basic ranges
const std::vector<uint32_t>* BasicRanges::fetch() { // get basic ranges content
if (status() != AVAILABLE) {
BasicRanges::build(); // basic ranges initialize
}
@ -46,7 +46,7 @@ void BasicRanges::build() { // ensure that basic ranges available
}
void BasicRanges::build_data() { // build basic ranges
BasicRanges::data.reserve(DATA_SIZE); // pre-allocated memory
BasicRanges::data.reserve(BASIC_RANGES_SIZE); // memory pre-allocated
for (int n = 0; n <= 7; ++n) { // number of 1x2 and 2x1 block -> 0 ~ 7
for (int n_2x1 = 0; n_2x1 <= n; ++n_2x1) { // number of 2x1 block -> 0 ~ n
for (int n_1x1 = 0; n_1x1 <= (14 - n * 2); ++n_1x1) { // number of 1x1 block -> 0 ~ (14 - 2n)

3
src/all_cases/basic_ranges.h

@ -4,6 +4,8 @@
#include <vector>
#include <cstdint>
const uint32_t BASIC_RANGES_SIZE = 7311921;
class BasicRanges {
public:
enum Status {
@ -19,7 +21,6 @@ private:
static bool available;
static std::mutex building;
static std::vector<uint32_t> data;
static const uint32_t DATA_SIZE = 7311921;
static void build_data();
static void generate(int n1, int n2, int n3, int n4);

11
src/main.cc

@ -209,10 +209,19 @@ int main() {
// }
BasicRanges::build();
// BasicRanges::build();
// for (auto const &range : *BasicRanges::fetch()) {
// printf("%08X\n", range);
// }
AllCases::build();
// for (uint32_t head = 0; head < 16; ++head) {
// uint64_t prefix = (uint64_t)head << 32;
// for (auto const &range : (*AllCases::fetch())[head]) {
// printf("%09lX\n", prefix | range);
// }
// }
std::cout << (clock() - start_time) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl;

Loading…
Cancel
Save