Skip to content

Commit 6f8e6d3

Browse files
authored
Update permpure_full.cpp
1 parent a289a35 commit 6f8e6d3

1 file changed

Lines changed: 84 additions & 90 deletions

File tree

permpure_full.cpp

Lines changed: 84 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,25 @@
55
* @license This project is licensed under the MIT License - see the LICENSE file for details.
66
* * Program Details:
77
* - Implements an efficient iterative permutation generation logic.
8-
* - Features: Windows CPU Affinity binding, High-precision timing (QPC),
8+
* - Features: Cross-platform CPU Affinity binding, High-precision timing (std::chrono),
99
* and optimization-resistant checksums.
1010
* - Performance: Designed for minimal branch misprediction and low overhead.
1111
* * Environment:
12-
* - Platform: Windows (Requires <windows.h>)
12+
* - Platform: Windows / Linux (Auto-switching headers)
1313
* - Compiler: GCC/MinGW (supports __builtin_LINE) or MSVC
14-
* * Usage:
15-
* Adjust the 'PERM_SIZE' macro to change the permutation set size.
16-
* Note: PERM_SIZE > 14 may require significant time.
1714
*/
18-
#include "stdio.h"
19-
#include "time.h"
20-
#include "windows.h" // Add Windows API header file
15+
16+
#include <stdio.h>
17+
#include <time.h>
18+
#include <chrono>
19+
20+
#ifdef _WIN32
21+
#include <windows.h>
22+
#else
23+
#include <sched.h>
24+
#include <pthread.h>
25+
#endif
26+
2127
#ifndef PERM_SIZE
2228
#define PERM_SIZE 12
2329
#endif
@@ -26,101 +32,89 @@
2632
// #define DEBUG
2733

2834
#ifdef DEBUG
29-
#define COUNT_PROCESS() ProcessCount[__builtin_LINE()]++
35+
#define COUNT_PURECESS() ProcessCount[__builtin_LINE()]++
3036
#else
31-
#define COUNT_PROCESS() // Empty definition, no operation in non-DEBUG mode
37+
#define COUNT_PURECESS()
3238
#endif
3339

3440
int main() {
35-
36-
// Bind to CPU core (core 3)
37-
DWORD_PTR mask = 8; // CPU mask for core 3 (1 << 3 = 8)
38-
HANDLE thread = GetCurrentThread();
39-
SetThreadAffinityMask(thread, mask);
40-
// Add checksum to prevent over-optimization
41-
unsigned long long checksum = 0;
42-
43-
unsigned long long purecessCount[200] = {0};
44-
int volatile i = 0;
45-
int j = 0;
46-
int C[PERM_SIZE] = {0}, D[PERM_SIZE] = {0}, M[PERM_SIZE] = {0};
47-
48-
// High precision timer variables
49-
LARGE_INTEGER start, finish, frequency;
50-
double duration;
51-
52-
// Get high precision timer frequency
53-
QueryPerformanceFrequency(&frequency);
54-
// Record start time
55-
QueryPerformanceCounter(&start);
56-
57-
while (C[0] < 1) {
58-
COUNT_pureCESS();
59-
for (; i < PERM_SIZE-1; ++i) {
60-
COUNT_pureCESS();
61-
D[i] = D[C[i]];
62-
D[C[i]] = i;
63-
}
41+
// --- Set CPU Affinity for Accurate Benchmarking ---
42+
#ifdef _WIN32
43+
DWORD_PTR mask = 8; // CPU mask for core 3
44+
SetThreadAffinityMask(GetCurrentThread(), mask);
45+
#else
46+
cpu_set_t cpuset;
47+
CPU_ZERO(&cpuset);
48+
CPU_SET(1, &cpuset); // Bind to Core 1 on Linux
49+
sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
50+
#endif
6451

65-
for (int ii = 0; ii < PERM_SIZE; ii++)
66-
{
67-
COUNT_pureCESS();
68-
D[PERM_SIZE-1] = D[ii];
69-
D[ii] = PERM_SIZE-1;
70-
checksum += D[PERM_SIZE-1];
52+
unsigned long long checksum = 0;
53+
unsigned long long ProcessCount[200] = {0};
54+
int volatile i = 0;
55+
int j = 0;
56+
int C[PERM_SIZE] = {0}, D[PERM_SIZE] = {0}, M[PERM_SIZE] = {0};
57+
58+
// --- High Precision Timing ---
59+
auto start = std::chrono::high_resolution_clock::now();
60+
61+
// Main Algorithm Loop
62+
while (C[0] < 1) {
63+
COUNT_PURECESS();
64+
for (; i < PERM_SIZE-1; ++i) {
65+
COUNT_PURECESS();
66+
D[i] = D[C[i]];
67+
D[C[i]] = i;
68+
}
69+
70+
for (int ii = 0; ii < PERM_SIZE; ii++) {
71+
COUNT_PURECESS();
72+
D[PERM_SIZE-1] = D[ii];
73+
D[ii] = PERM_SIZE-1;
74+
checksum += D[PERM_SIZE-1];
7175

7276
#if PERM_SIZE <= LittleNumber
73-
// Print D array
74-
printf("\n");
75-
for (int jj = 0; jj < PERM_SIZE; jj++) {
76-
printf("%d,", D[jj]);
77-
}
77+
printf("\n");
78+
for (int jj = 0; jj < PERM_SIZE; jj++) {
79+
printf("%d,", D[jj]);
80+
}
7881
#endif
79-
D[ii] = D[PERM_SIZE-1];
80-
}
81-
82-
D[C[PERM_SIZE - 2]] = D[PERM_SIZE - 2];
83-
84-
C[PERM_SIZE - 2]++;
85-
for (i = PERM_SIZE - 2; (i > 0) && (C[i] > i); i--) {
86-
COUNT_pureCESS();
87-
C[i] = 0;
88-
C[i - 1]++;
89-
D[C[i - 1] - 1] = D[i - 1];
82+
D[ii] = D[PERM_SIZE-1];
83+
}
84+
85+
D[C[PERM_SIZE - 2]] = D[PERM_SIZE - 2];
86+
87+
C[PERM_SIZE - 2]++;
88+
for (i = PERM_SIZE - 2; (i > 0) && (C[i] > i); i--) {
89+
COUNT_PURECESS();
90+
C[i] = 0;
91+
C[i - 1]++;
92+
D[C[i - 1] - 1] = D[i - 1];
93+
}
9094
}
91-
}
9295

93-
// Record end time
94-
QueryPerformanceCounter(&finish);
95-
// Calculate duration (seconds) = (end count - start count) / frequency
96-
duration = (double)(finish.QuadPart - start.QuadPart) / frequency.QuadPart;
97-
printf("\npermpure_full\t%u\t%lf", PERM_SIZE, duration);
96+
auto finish = std::chrono::high_resolution_clock::now();
97+
std::chrono::duration<double> duration = finish - start;
9898

99-
// Prevent the compiler from optimizing too much
100-
printf("\nD[PERM_SIZE-1] = %d, checksum = %llu", D[PERM_SIZE-1], checksum);
99+
printf("\npermpure_full\t%u\t%lf seconds", PERM_SIZE, duration.count());
100+
printf("\nD[PERM_SIZE-1] = %d, checksum = %llu\n", D[PERM_SIZE-1], checksum);
101101

102102
#ifdef DEBUG
103-
unsigned long long perm = 1;
104-
unsigned long long PermValue[PERM_SIZE] = {0};
105-
unsigned long long SumPermValue[PERM_SIZE] = {0};
106-
PermValue[0] = 1;
107-
SumPermValue[0] = 0;
108-
for (i = 1; i <= PERM_SIZE; i++) {
109-
perm = perm * i; // Calculate factorial: perm = i!
110-
PermValue[i] = perm; // Store current factorial value
111-
SumPermValue[i] = SumPermValue[i - 1] + perm; // Calculate cumulative factorial sum
112-
}
113-
114-
// Print i, permvalue, SumPermvalue
115-
for (i = 1; i <= PERM_SIZE; i++) {
116-
printf("\n%u !, %llu, sigma %llu", i, PermValue[i], SumPermValue[i]);
117-
}
118-
119-
for (i = 0; i < 100; i++)
120-
if (ProcessCount[i] > 0)
121-
printf("\n [Line %u]%llu", i, ProcessCount[i]);
103+
// Debug info logic preserved
104+
unsigned long long perm = 1;
105+
unsigned long long PermValue[PERM_SIZE + 1] = {0};
106+
unsigned long long SumPermValue[PERM_SIZE + 1] = {0};
107+
PermValue[0] = 1;
108+
SumPermValue[0] = 0;
109+
for (int k = 1; k <= PERM_SIZE; k++) {
110+
perm = perm * k;
111+
PermValue[k] = perm;
112+
SumPermValue[k] = SumPermValue[k - 1] + perm;
113+
}
114+
for (int k = 1; k <= PERM_SIZE; k++) {
115+
printf("\n%u !, %llu, sigma %llu", k, PermValue[k], SumPermValue[k]);
116+
}
122117
#endif
123118

124-
return 0;
125-
119+
return 0;
126120
}

0 commit comments

Comments
 (0)