Skip to content

Commit 0c1f50d

Browse files
authored
Merge pull request #2994 from pareenaverma/content_review
Moved bsort code out separately
2 parents c1466c1 + bf08f24 commit 0c1f50d

2 files changed

Lines changed: 116 additions & 115 deletions

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <time.h>
4+
5+
#define ARRAY_LEN 10000
6+
#define FUNC_COPIES 5
7+
volatile bool Cond = false;
8+
#define COND() (__builtin_expect(Cond, true))
9+
10+
#define NOPS(N) \
11+
asm volatile( \
12+
".rept %0\n" \
13+
"nop\n" \
14+
".endr\n" \
15+
: : "i"(N) : "memory")
16+
17+
// Swap functionality plus some cold blocks.
18+
#define SWAP_FUNC(ID) \
19+
static __attribute__((noinline)) \
20+
void swap##ID(int *left, int *right) { \
21+
if (COND()) NOPS(300); \
22+
int tmp = *left; \
23+
if (COND()) NOPS(300); else *left = *right; \
24+
if (COND()) NOPS(300); else *right = tmp; \
25+
}
26+
27+
// Aligned at 16KiB
28+
#define COLD_FUNC(ID) \
29+
static __attribute__((noinline, aligned(16384), used)) \
30+
void cold_func##ID(void) { \
31+
asm volatile("nop"); \
32+
}
33+
34+
// Create copies of swap, and interleave with big chunks of cold code.
35+
SWAP_FUNC(1) COLD_FUNC(1)
36+
SWAP_FUNC(2) COLD_FUNC(2)
37+
SWAP_FUNC(3) COLD_FUNC(3)
38+
SWAP_FUNC(4) COLD_FUNC(4)
39+
SWAP_FUNC(5) COLD_FUNC(5)
40+
41+
typedef void (*swap_fty)(int *, int *);
42+
static swap_fty const swap_funcs[FUNC_COPIES] = {
43+
swap1, swap2, swap3, swap4, swap5
44+
};
45+
46+
47+
/* Sorting Logic */
48+
void bubble_sort(int *a, int n) {
49+
if (n <= 1)
50+
return;
51+
52+
int end = n - 1;
53+
int swapped = 1;
54+
unsigned idx = 0;
55+
56+
while (swapped && end > 0) {
57+
swapped = 0;
58+
// pick a different copy of the swap function, in a round-robin fashion
59+
// and call it.
60+
for (int i = 1; i <= end; ++i) {
61+
if (a[i] < a[i - 1]) {
62+
auto swap_func = swap_funcs[idx++];
63+
idx %= FUNC_COPIES;
64+
swap_func(&a[i - 1], &a[i]);
65+
swapped = 1;
66+
}
67+
}
68+
--end;
69+
}
70+
}
71+
72+
void sort_array(int *data) {
73+
for (int i = 0; i < ARRAY_LEN; ++i) {
74+
data[i] = rand();
75+
}
76+
bubble_sort(data, ARRAY_LEN);
77+
}
78+
79+
/* Timers, helpers, and main */
80+
static struct timespec timer_start;
81+
static inline void start_timer(void) {
82+
clock_gettime(CLOCK_MONOTONIC, &timer_start);
83+
}
84+
85+
static inline void stop_timer(void) {
86+
struct timespec timer_end;
87+
clock_gettime(CLOCK_MONOTONIC, &timer_end);
88+
long long ms = (timer_end.tv_sec - timer_start.tv_sec) * 1000LL +
89+
(timer_end.tv_nsec - timer_start.tv_nsec) / 1000000LL;
90+
printf("%lld ms ", ms);
91+
}
92+
93+
static void print_first_last(const int *data, int n) {
94+
if (n <= 0)
95+
return;
96+
97+
const int first = data[0];
98+
const int last = data[n - 1];
99+
printf("(first=%d last=%d)\n", first, last);
100+
}
101+
102+
int main(void) {
103+
srand(0);
104+
printf("Bubble sorting %d elements\n", ARRAY_LEN);
105+
int data[ARRAY_LEN];
106+
107+
start_timer();
108+
sort_array(data);
109+
stop_timer();
110+
111+
print_first_last(data, ARRAY_LEN);
112+
return 0;
113+
}

content/learning-paths/servers-and-cloud-computing/bolt-demo/setup.md

Lines changed: 3 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -8,122 +8,10 @@ layout: learningpathall
88

99

1010
## Set up your environment
11-
On your AArch64 Linux machine, navigate to your home directory (or another empty working directory) and create a file named `bsort.cpp` with the following content:
11+
On your AArch64 Linux machine, navigate to your home directory (or another empty working directory) and download the `bsort.cpp` source file:
1212

13-
```cpp
14-
#include <stdio.h>
15-
#include <stdlib.h>
16-
#include <time.h>
17-
18-
#define ARRAY_LEN 10000
19-
#define FUNC_COPIES 5
20-
volatile bool Cond = false;
21-
#define COND() (__builtin_expect(Cond, true))
22-
23-
#define NOPS(N) \
24-
asm volatile( \
25-
".rept %0\n" \
26-
"nop\n" \
27-
".endr\n" \
28-
: : "i"(N) : "memory")
29-
30-
// Swap functionality plus some cold blocks.
31-
#define SWAP_FUNC(ID) \
32-
static __attribute__((noinline)) \
33-
void swap##ID(int *left, int *right) { \
34-
if (COND()) NOPS(300); \
35-
int tmp = *left; \
36-
if (COND()) NOPS(300); else *left = *right; \
37-
if (COND()) NOPS(300); else *right = tmp; \
38-
}
39-
40-
// Aligned at 16KiB
41-
#define COLD_FUNC(ID) \
42-
static __attribute__((noinline, aligned(16384), used)) \
43-
void cold_func##ID(void) { \
44-
asm volatile("nop"); \
45-
}
46-
47-
// Create copies of swap, and interleave with big chunks of cold code.
48-
SWAP_FUNC(1) COLD_FUNC(1)
49-
SWAP_FUNC(2) COLD_FUNC(2)
50-
SWAP_FUNC(3) COLD_FUNC(3)
51-
SWAP_FUNC(4) COLD_FUNC(4)
52-
SWAP_FUNC(5) COLD_FUNC(5)
53-
54-
typedef void (*swap_fty)(int *, int *);
55-
static swap_fty const swap_funcs[FUNC_COPIES] = {
56-
swap1, swap2, swap3, swap4, swap5
57-
};
58-
59-
60-
/* Sorting Logic */
61-
void bubble_sort(int *a, int n) {
62-
if (n <= 1)
63-
return;
64-
65-
int end = n - 1;
66-
int swapped = 1;
67-
unsigned idx = 0;
68-
69-
while (swapped && end > 0) {
70-
swapped = 0;
71-
// pick a different copy of the swap function, in a round-robin fashion
72-
// and call it.
73-
for (int i = 1; i <= end; ++i) {
74-
if (a[i] < a[i - 1]) {
75-
auto swap_func = swap_funcs[idx++];
76-
idx %= FUNC_COPIES;
77-
swap_func(&a[i - 1], &a[i]);
78-
swapped = 1;
79-
}
80-
}
81-
--end;
82-
}
83-
}
84-
85-
void sort_array(int *data) {
86-
for (int i = 0; i < ARRAY_LEN; ++i) {
87-
data[i] = rand();
88-
}
89-
bubble_sort(data, ARRAY_LEN);
90-
}
91-
92-
/* Timers, helpers, and main */
93-
static struct timespec timer_start;
94-
static inline void start_timer(void) {
95-
clock_gettime(CLOCK_MONOTONIC, &timer_start);
96-
}
97-
98-
static inline void stop_timer(void) {
99-
struct timespec timer_end;
100-
clock_gettime(CLOCK_MONOTONIC, &timer_end);
101-
long long ms = (timer_end.tv_sec - timer_start.tv_sec) * 1000LL +
102-
(timer_end.tv_nsec - timer_start.tv_nsec) / 1000000LL;
103-
printf("%lld ms ", ms);
104-
}
105-
106-
static void print_first_last(const int *data, int n) {
107-
if (n <= 0)
108-
return;
109-
110-
const int first = data[0];
111-
const int last = data[n - 1];
112-
printf("(first=%d last=%d)\n", first, last);
113-
}
114-
115-
int main(void) {
116-
srand(0);
117-
printf("Bubble sorting %d elements\n", ARRAY_LEN);
118-
int data[ARRAY_LEN];
119-
120-
start_timer();
121-
sort_array(data);
122-
stop_timer();
123-
124-
print_first_last(data, ARRAY_LEN);
125-
return 0;
126-
}
13+
```bash
14+
wget https://raw.githubusercontent.com/ArmDeveloperEcosystem/arm-learning-paths/main/content/learning-paths/servers-and-cloud-computing/bolt-demo/bsort.cpp
12715
```
12816

12917
The [Why Bubble Sort?](#why-bubble-sort) section explains why BubbleSort is used as the demonstration workload.

0 commit comments

Comments
 (0)