// WETSort.cpp : This file contains the 'main' function. Program execution begins and ends there. // #include "../arkiny/dclb/Sort.h" #include "../ccm9026/JFSort/JFSort.h" #include "../djarksnd/sort.h" #include "../insun/Sort/Sort/SquickSort.h" #define partition es_partition #include "../prauser/ESSort.h" #undef partition #include "../witdrg/wc.h" #include #include #include #include #include #include std::string sha1(const void* p, size_t s); const size_t testLength[] = { #ifdef _DEBUG 1ULL << 21, 1ULL << 24, 1ULL << 29, #else 1ULL << 31, // 2G (4G) 1ULL << 32, // 4G (8G) 1ULL << 33 // 8G (16G) #endif }; enum TestUnitId { stl = -1, arkiny = 0, ccm9026, djarksnd, insun, prauser, witdrg, MAX_UID }; const char* uidString[MAX_UID] = { "arkiny", "ccm9026", "djarksnd", "insun", "prauser", "witdrg" }; struct TestScore { bool error; double sum; int num; }; TestScore testScore[MAX_UID] = { 0 }; struct TestResult { double t; std::string hash; }; enum GenerateDataTypes { GenUniform32, GenUniform16, GenUniform16Xor, GenUniform8, GenUniform4, GenUniform1, GenUniform8Xor, GenNormal64, GenNormal32, }; #pragma pack(push, 1) template struct Element { int8_t buffer[s]; bool operator < (const Element& other) const { for (size_t i = 0; i < s; ++i) { int n = int(buffer[i]) - int(other.buffer[i]); if (n) return n > 0; } return false; } }; #pragma pack(pop) static std::vector data0, data1; template TestResult TestUnit(int index) { std::function fn; switch (index) { case stl: fn = [](ElementType* items, size_t numItems) { std::sort(&items[0], &items[numItems], std::less()); }; break; case arkiny: fn = [](ElementType* items, size_t numItems) { dc::sort(&items[0], &items[numItems], std::less()); }; break; case ccm9026: fn = [](ElementType* items, size_t numItems) { JFFoundation::JFAlgorithm::_Sort(&items[0], &items[numItems], std::less()); }; break; case djarksnd: fn = [](ElementType* items, size_t numItems) { sort::sort(&items[0], &items[numItems], std::less()); }; break; case insun: fn = [](ElementType* items, size_t numItems) { SunSort::SSort(items, &items[0], &items[numItems - 1], std::less()); }; break; case prauser: fn = [](ElementType* items, size_t numItems) { // ERROR //std::less tmp; //ES::quickSort>(&items[0], &items[numItems], tmp); }; break; case witdrg: fn = [](ElementType* items, size_t numItems) { // ERROR //wc::sort(&items[0], &items[numItems], std::less()); }; break; } if (fn) { std::chrono::high_resolution_clock clock; using sec = std::chrono::duration>; data1.resize(data0.size()); memcpy(data1.data(), data0.data(), data0.size()); size_t s = sizeof(ElementType); size_t numItems = data1.size() / s; auto start = clock.now(); fn(reinterpret_cast(data1.data()), numItems); auto end = clock.now(); TestResult res; res.t = std::chrono::duration_cast(end - start).count(); res.hash = sha1(data1.data(), data1.size()).c_str(); return res; } throw std::runtime_error("unexpected error!"); } template void DoSortTest(void) { size_t numItems = data0.size() / unitSize; TestResult base = TestUnit>(stl); printf("[%s] items: %zu / %zu, elapsed: %f, hash: %s\n", "STD", unitSize, numItems, base.t, base.hash.c_str()); for (int i = 0; i < MAX_UID; ++i) { TestScore& score = testScore[i]; if (!score.error) { //printf("[%s] sorting...\n", uidString[i]); TestResult r = TestUnit>(i); if (base.hash == r.hash) { double s = base.t / r.t; score.sum += s; score.num++; printf("[%s] items: %zu, elapsed: %f, score:%d\n", uidString[i], numItems, r.t, int(s * 100)); } else { printf("[%s] error!! [REJECTED]\n", uidString[i]); score.error = true; } } } } void RunTest(size_t size, GenerateDataTypes type) { std::random_device rdev; std::default_random_engine re(rdev()); if (1) { size_t s = 64; while (s < size) s <<= 1; size = s; } // generate random number. data0.clear(); data0.resize(size); switch (type) { case GenUniform32: if (1) { printf("Generating random data... (%zu bytes, type: Uniform32)\n", size); std::uniform_int_distribution dist(0, 0xffffffff); for (size_t i = 0, e = size / sizeof(uint32_t); i < e; ++i) { reinterpret_cast(data0.data())[i] = dist(re); } } break; case GenUniform16: if (1) { printf("Generating random data... (%zu bytes, type: Uniform16)\n", size); std::uniform_int_distribution dist(0, 0xffff); for (size_t i = 0, e = size / sizeof(uint32_t); i < e; ++i) { reinterpret_cast(data0.data())[i] = dist(re); } } break; case GenUniform16Xor: if (1) { printf("Generating random data... (%zu bytes, type: Uniform16Xor)\n", size); std::uniform_int_distribution dist(0, 0xffff); uint32_t tmp = dist(re); for (size_t i = 0, e = size / sizeof(uint32_t); i < e; ++i) { uint32_t x = dist(re); uint32_t y = (i ^ (tmp << 3)) & 0xff; tmp = y; reinterpret_cast(data0.data())[i] = (x << 16) | y; } } break; case GenUniform8: if (1) { printf("Generating random data... (%zu bytes, type: Uniform8)\n", size); std::uniform_int_distribution dist(0, 0xff); for (size_t i = 0, e = size / sizeof(uint32_t); i < e; ++i) { reinterpret_cast(data0.data())[i] = dist(re); } } break; case GenUniform8Xor: if (1) { printf("Generating random data... (%zu bytes, type: Uniform8Xor)\n", size); std::uniform_int_distribution dist(0, 0xff); uint32_t tmp = dist(re); for (size_t i = 0, e = size / sizeof(uint32_t); i < e; ++i) { uint32_t val = dist(re); val = val ^ (tmp << 1); tmp = val; reinterpret_cast(data0.data())[i] = val; } } break; case GenUniform4: if (1) { printf("Generating random data... (%zu bytes, type: Uniform8)\n", size); std::uniform_int_distribution dist(0, 0xff); for (size_t i = 0, e = size / sizeof(uint32_t); i < e; ++i) { reinterpret_cast(data0.data())[i] = dist(re) & 0x7; } } break; case GenUniform1: if (1) { printf("Generating random data... (%zu bytes, type: Uniform8)\n", size); std::uniform_int_distribution dist(0, 0xff); for (size_t i = 0, e = size / sizeof(uint32_t); i < e; ++i) { reinterpret_cast(data0.data())[i] = dist(re) & 0x1; } } break; case GenNormal64: if (1) { printf("Generating random data... (%zu bytes, type: Normal64)\n", size); std::normal_distribution dist; for (size_t i = 0, e = size / sizeof(double); i < e; ++i) { reinterpret_cast(data0.data())[i] = dist(re); } } break; case GenNormal32: if (1) { printf("Generating random data... (%zu bytes, type: Normal32)\n", size); std::normal_distribution dist; for (size_t i = 0, e = size / sizeof(float); i < e; ++i) { reinterpret_cast(data0.data())[i] = dist(re); } } break; } // 1 byte DoSortTest<1>(); // 2 byte DoSortTest<2>(); // 3 bytes DoSortTest<3>(); //4 bytes DoSortTest<4>(); // 5 bytes DoSortTest<5>(); // 6 DoSortTest<6>(); // 7 DoSortTest<7>(); // 9 bytes DoSortTest<9>(); // 10 DoSortTest<10>(); // 11 DoSortTest<11>(); // 12 DoSortTest<12>(); // 13 DoSortTest<13>(); // 15 DoSortTest<15>(); // 17 bytes DoSortTest<17>(); //// 32 bytes //DoSortTest<32>(); //// 33 bytes //DoSortTest<33>(); } int main() { // Set .error to '0' to run the test! testScore[arkiny].error = 1; testScore[ccm9026].error = 1; testScore[djarksnd].error = 1; testScore[insun].error = 1; testScore[prauser].error = 1; testScore[witdrg].error = 1; auto dataTypes = { GenUniform32, GenUniform16, GenUniform16Xor, GenUniform8, GenUniform8Xor, GenUniform4, GenUniform1, GenNormal64, GenNormal32 }; auto PrintScore = [](int phase) { printf("------------ SCORE (%d/%d) --------------\n", phase, int(std::size(testLength))); for (int i = 0; i < MAX_UID; ++i) { const TestScore& score = testScore[i]; if (score.error) { printf("UID(%s) rejected. (ERROR)\n", uidString[i]); } else { uint32_t s = (score.sum / double(score.num)) * 100.0; const char* t = ""; if (s > 100) t = "(PERFECT)"; else if (s > 90) t = "(GOOD)"; else if (s < 60) t = "(POOR)"; printf("UID(%s) score: %d. %s\n", uidString[i], s, t); } } printf("-----------------------------------------\n\n"); }; int index = 1; for (size_t n : testLength) { printf("========= Phase %d / %d (%zu) ==========\n", index, int(std::size(testLength)), n); for (auto t : dataTypes) { RunTest(n, t); } PrintScore(index); index++; } }