Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
las3_pub
/
predictable_parallel_patterns
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
e2f584c4
authored
4 years ago
by
FritzFlorian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow flexible problem sizes and periodic execution for benchmarks.
parent
d32bba10
Pipeline
#1513
passed with stages
in 4 minutes 33 seconds
Changes
6
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
293 additions
and
114 deletions
+293
-114
app/benchmark_fft/main.cpp
+27
-18
app/benchmark_fib/main.cpp
+28
-19
app/benchmark_matrix/main.cpp
+27
-17
app/benchmark_matrix_div_conquer/main.cpp
+28
-16
app/benchmark_unbalanced/main.cpp
+29
-31
extern/benchmark_runner/benchmark_runner.h
+154
-13
No files found.
app/benchmark_fft/main.cpp
View file @
e2f584c4
...
...
@@ -31,35 +31,44 @@ constexpr int MAX_NUM_TASKS = 16;
constexpr
int
MAX_STACK_SIZE
=
4096
*
1
;
int
main
(
int
argc
,
char
**
argv
)
{
int
num_threads
;
string
directory
;
benchmark_runner
::
read_args
(
argc
,
argv
,
num_threads
,
directory
);
auto
settings
=
benchmark_runner
::
parse_parameters
(
argc
,
argv
);
string
test_name
=
to_string
(
num_threads
)
+
".csv"
;
string
full_directory
=
directory
+
"/PLS_v3/"
;
fft
::
complex_vector
data
(
settings
.
size_
);
fft
::
complex_vector
swap_array
(
settings
.
size_
);
fft
::
fill_input
(
data
);
string
test_name
=
to_string
(
settings
.
num_threads_
)
+
".csv"
;
string
full_directory
=
settings
.
output_directory_
+
"/PLS_v3/"
;
benchmark_runner
runner
{
full_directory
,
test_name
};
runner
.
enable_memory_stats
();
runner
.
pre_allocate_stats
();
fft
::
complex_vector
data
(
fft
::
SIZE
);
fft
::
complex_vector
swap_array
(
fft
::
SIZE
);
fft
::
fill_input
(
data
);
pls
::
scheduler
scheduler
{(
unsigned
)
settings
.
num_threads_
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
pls
::
scheduler
scheduler
{(
unsigned
)
num_threads
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
if
(
settings
.
type_
==
benchmark_runner
::
benchmark_settings
::
ISOLATED
)
{
printf
(
"Running isolated measurement...
\n
"
);
runner
.
enable_memory_stats
();
runner
.
pre_allocate_stats
();
// scheduler.get_profiler().disable_memory_measure();
runner
.
run_iterations
(
fft
::
NUM_ITERATIONS
,
[
&
]()
{
runner
.
run_iterations
(
settings
.
iterations_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
pls_conquer
(
data
.
begin
(),
swap_array
.
begin
(),
fft
::
SIZE
);;
pls_conquer
(
data
.
begin
(),
swap_array
.
begin
(),
settings
.
size_
);;
});
// scheduler.get_profiler().current_run().print_stats();
},
fft
::
NUM_WARMUP_ITERATIONS
,
[
&
]()
{
},
[
&
]()
{
fft
::
fill_input
(
data
);
// Reset data before each run
});
// scheduler.get_profiler().current_run().print_dag(std::cout);
// scheduler.get_profiler().current_run().print_stats();
runner
.
commit_results
(
true
);
}
else
{
printf
(
"Running periodic measurement...
\n
"
);
runner
.
enable_wall_time_stats
();
runner
.
pre_allocate_stats
();
runner
.
run_periodic
(
settings
.
iterations_
,
settings
.
interval_period_
,
settings
.
interval_deadline_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
pls_conquer
(
data
.
begin
(),
swap_array
.
begin
(),
settings
.
size_
);;
});
fft
::
fill_input
(
data
);
// Reset data before each run
});
runner
.
commit_results
(
true
);
}
return
0
;
}
This diff is collapsed.
Click to expand it.
app/benchmark_fib/main.cpp
View file @
e2f584c4
...
...
@@ -8,7 +8,7 @@ using namespace comparison_benchmarks::base;
constexpr
int
MAX_NUM_TASKS
=
32
;
constexpr
int
MAX_STACK_SIZE
=
4096
*
1
;
int
pls_fib
(
int
n
,
int
d
)
{
int
pls_fib
(
int
n
)
{
if
(
n
==
0
)
{
return
0
;
}
...
...
@@ -17,11 +17,11 @@ int pls_fib(int n, int d) {
}
int
a
,
b
;
pls
::
spawn
([
n
,
d
,
&
a
]()
{
a
=
pls_fib
(
n
-
1
,
d
+
1
);
pls
::
spawn
([
n
,
&
a
]()
{
a
=
pls_fib
(
n
-
1
);
});
pls
::
spawn
([
n
,
d
,
&
b
]()
{
b
=
pls_fib
(
n
-
2
,
d
+
1
);
pls
::
spawn
([
n
,
&
b
]()
{
b
=
pls_fib
(
n
-
2
);
});
pls
::
sync
();
...
...
@@ -29,29 +29,38 @@ int pls_fib(int n, int d) {
}
int
main
(
int
argc
,
char
**
argv
)
{
int
num_threads
;
string
directory
;
benchmark_runner
::
read_args
(
argc
,
argv
,
num_threads
,
directory
);
auto
settings
=
benchmark_runner
::
parse_parameters
(
argc
,
argv
);
string
test_name
=
to_string
(
num_threads
)
+
".csv"
;
string
full_directory
=
directory
+
"/PLS_v3/"
;
string
test_name
=
to_string
(
settings
.
num_threads_
)
+
".csv"
;
string
full_directory
=
settings
.
output_directory_
+
"/PLS_v3/"
;
benchmark_runner
runner
{
full_directory
,
test_name
};
runner
.
enable_memory_stats
();
runner
.
pre_allocate_stats
();
pls
::
scheduler
scheduler
{(
unsigned
)
num_threads
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
pls
::
scheduler
scheduler
{(
unsigned
)
settings
.
num_threads_
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
volatile
int
res
;
// scheduler.get_profiler().disable_memory_measure();
runner
.
run_iterations
(
fib
::
NUM_ITERATIONS
,
[
&
]()
{
if
(
settings
.
type_
==
benchmark_runner
::
benchmark_settings
::
ISOLATED
)
{
printf
(
"Running isolated measurement...
\n
"
);
runner
.
enable_memory_stats
();
runner
.
pre_allocate_stats
();
runner
.
run_iterations
(
settings
.
iterations_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
res
=
pls_fib
(
fib
::
INPUT_N
,
0
);
res
=
pls_fib
(
settings
.
size_
);
});
});
},
fib
::
NUM_WARMUP_ITERATIONS
);
// scheduler.get_profiler().current_run().print_dag(std::cout);
// scheduler.get_profiler().current_run().print_stats();
runner
.
commit_results
(
true
);
}
else
{
printf
(
"Running periodic measurement...
\n
"
);
runner
.
enable_wall_time_stats
();
runner
.
pre_allocate_stats
();
runner
.
run_periodic
(
settings
.
iterations_
,
settings
.
interval_period_
,
settings
.
interval_deadline_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
res
=
pls_fib
(
settings
.
size_
);
});
});
runner
.
commit_results
(
true
);
}
return
0
;
}
This diff is collapsed.
Click to expand it.
app/benchmark_matrix/main.cpp
View file @
e2f584c4
...
...
@@ -20,34 +20,44 @@ class pls_matrix : public matrix::matrix<T> {
}
};
constexpr
int
MAX_NUM_TASKS
=
32
;
constexpr
int
MAX_NUM_TASKS
=
10
;
constexpr
int
MAX_STACK_SIZE
=
4096
*
1
;
int
main
(
int
argc
,
char
**
argv
)
{
int
num_threads
;
string
directory
;
benchmark_runner
::
read_args
(
argc
,
argv
,
num_threads
,
directory
);
auto
settings
=
benchmark_runner
::
parse_parameters
(
argc
,
argv
);
string
test_name
=
to_string
(
num_threads
)
+
".csv"
;
string
full_directory
=
directory
+
"/PLS_v3/"
;
pls_matrix
<
double
>
a
{
settings
.
size_
};
pls_matrix
<
double
>
b
{
settings
.
size_
};
pls_matrix
<
double
>
result
{
settings
.
size_
};
string
test_name
=
to_string
(
settings
.
num_threads_
)
+
".csv"
;
string
full_directory
=
settings
.
output_directory_
+
"/PLS_v3/"
;
benchmark_runner
runner
{
full_directory
,
test_name
};
runner
.
enable_memory_stats
();
runner
.
pre_allocate_stats
();
pls_matrix
<
double
>
a
{
matrix
::
MATRIX_SIZE
};
pls_matrix
<
double
>
b
{
matrix
::
MATRIX_SIZE
};
pls_matrix
<
double
>
result
{
matrix
::
MATRIX_SIZE
};
pls
::
scheduler
scheduler
{(
unsigned
)
settings
.
num_threads_
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
scheduler
scheduler
{(
unsigned
)
num_threads
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
if
(
settings
.
type_
==
benchmark_runner
::
benchmark_settings
::
ISOLATED
)
{
printf
(
"Running isolated measurement...
\n
"
);
runner
.
enable_memory_stats
();
runner
.
pre_allocate_stats
();
// scheduler.get_profiler().disable_memory_measure();
runner
.
run_iterations
(
matrix
::
NUM_ITERATIONS
,
[
&
]()
{
runner
.
run_iterations
(
settings
.
iterations_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
result
.
multiply
(
a
,
b
);
});
},
matrix
::
WARMUP_ITERATIONS
);
// scheduler.get_profiler().current_run().print_dag(std::cout);
// scheduler.get_profiler().current_run().print_stats();
});
runner
.
commit_results
(
true
);
}
else
{
printf
(
"Running periodic measurement...
\n
"
);
runner
.
enable_wall_time_stats
();
runner
.
pre_allocate_stats
();
runner
.
run_periodic
(
settings
.
iterations_
,
settings
.
interval_period_
,
settings
.
interval_deadline_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
result
.
multiply
(
a
,
b
);
});
});
runner
.
commit_results
(
true
);
}
}
This diff is collapsed.
Click to expand it.
app/benchmark_matrix_div_conquer/main.cpp
View file @
e2f584c4
...
...
@@ -99,21 +99,13 @@ void multiply_div_conquer(const std::vector<std::vector<std::vector<std::unique_
}
}
constexpr
int
MAX_NUM_TASKS
=
32
;
constexpr
int
MAX_NUM_TASKS
=
16
;
constexpr
int
MAX_STACK_SIZE
=
4096
*
2
;
int
main
(
int
argc
,
char
**
argv
)
{
const
size_t
size
=
matrix_div_conquer
::
MATRIX_SIZE
;
auto
settings
=
benchmark_runner
::
parse_parameters
(
argc
,
argv
);
const
size_t
size
=
settings
.
size_
;
int
num_threads
;
string
directory
;
benchmark_runner
::
read_args
(
argc
,
argv
,
num_threads
,
directory
);
string
test_name
=
to_string
(
num_threads
)
+
".csv"
;
string
full_directory
=
directory
+
"/PLS_v3/"
;
benchmark_runner
runner
{
full_directory
,
test_name
};
runner
.
enable_memory_stats
();
runner
.
pre_allocate_stats
();
// Only run on one version to avoid copy
std
::
unique_ptr
<
double
[]
>
result_data
{
new
double
[
size
*
size
]};
...
...
@@ -145,16 +137,36 @@ int main(int argc, char **argv) {
max_depth
++
;
remaining_size
=
remaining_size
/
2
;
}
pls
::
strain_local_resource
local_indices
{(
unsigned
)
num_threads
,
(
unsigned
)
max_depth
};
pls
::
strain_local_resource
local_indices
{(
unsigned
)
settings
.
num_threads_
,
(
unsigned
)
max_depth
};
string
test_name
=
to_string
(
settings
.
num_threads_
)
+
".csv"
;
string
full_directory
=
settings
.
output_directory_
+
"/PLS_v3/"
;
benchmark_runner
runner
{
full_directory
,
test_name
};
pls
::
scheduler
scheduler
{(
unsigned
)
settings
.
num_threads_
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
if
(
settings
.
type_
==
benchmark_runner
::
benchmark_settings
::
ISOLATED
)
{
printf
(
"Running isolated measurement...
\n
"
);
runner
.
enable_memory_stats
();
runner
.
pre_allocate_stats
();
scheduler
scheduler
{(
unsigned
)
num_threads
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
runner
.
run_iterations
(
settings
.
iterations_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
multiply_div_conquer
(
div_conquer_temp_arrays
,
local_indices
,
size
,
0
,
result
,
a
,
b
);
});
});
runner
.
commit_results
(
true
);
}
else
{
printf
(
"Running periodic measurement...
\n
"
);
runner
.
enable_wall_time_stats
();
runner
.
pre_allocate_stats
();
runner
.
run_iterations
(
1
,
[
&
]()
{
runner
.
run_periodic
(
settings
.
iterations_
,
settings
.
interval_period_
,
settings
.
interval_deadline_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
multiply_div_conquer
(
div_conquer_temp_arrays
,
local_indices
,
size
,
0
,
result
,
a
,
b
);
});
},
0
);
}
);
runner
.
commit_results
(
true
);
}
scheduler
.
terminate
();
}
This diff is collapsed.
Click to expand it.
app/benchmark_unbalanced/main.cpp
View file @
e2f584c4
#include "pls/
internal/scheduling/scheduler
.h"
#include "pls/
pls
.h"
using
namespace
pls
::
internal
::
scheduling
;
...
...
@@ -16,12 +16,12 @@ int count_child_nodes(unbalanced::node &node) {
std
::
atomic
<
int
>
count
{
1
};
for
(
int
i
=
0
;
i
<
node
.
get_num_children
();
i
++
)
{
scheduler
::
spawn
([
i
,
&
count
,
&
node
]
{
pls
::
spawn
([
i
,
&
count
,
&
node
]
{
unbalanced
::
node
child_node
=
node
.
spawn_child_node
(
i
);
count
.
fetch_add
(
count_child_nodes
(
child_node
));
});
}
scheduler
::
sync
();
pls
::
sync
();
return
count
;
}
...
...
@@ -32,49 +32,47 @@ int unbalanced_tree_search(int seed, int root_children, double q, int normal_chi
}
constexpr
int
MAX_NUM_TASKS
=
256
;
constexpr
int
MAX_STACK_SIZE
=
1024
*
2
;
constexpr
int
MAX_STACK_SIZE
=
4096
*
1
;
int
main
(
int
argc
,
char
**
argv
)
{
int
num_threads
;
string
directory
;
benchmark_runner
::
read_args
(
argc
,
argv
,
num_threads
,
directory
);
auto
settings
=
benchmark_runner
::
parse_parameters
(
argc
,
argv
);
string
test_name
=
to_string
(
num_threads
)
+
".csv"
;
string
full_directory
=
directory
+
"/PLS_v3/"
;
string
test_name
=
to_string
(
settings
.
num_threads_
)
+
".csv"
;
string
full_directory
=
settings
.
output_directory_
+
"/PLS_v3/"
;
benchmark_runner
runner
{
full_directory
,
test_name
};
pls
::
scheduler
scheduler
{(
unsigned
)
settings
.
num_threads_
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
if
(
settings
.
type_
==
benchmark_runner
::
benchmark_settings
::
ISOLATED
)
{
printf
(
"Running isolated measurement...
\n
"
);
runner
.
enable_memory_stats
();
runner
.
pre_allocate_stats
();
scheduler
scheduler
{(
unsigned
)
num_threads
,
MAX_NUM_TASKS
,
MAX_STACK_SIZE
};
runner
.
run_iterations
(
settings
.
iterations_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
unbalanced_tree_search
(
unbalanced
::
SEED
,
unbalanced
::
ROOT_CHILDREN
,
unbalanced
::
Q
,
unbalanced
::
NORMAL_CHILDREN
);
});
});
runner
.
commit_results
(
true
);
}
else
{
printf
(
"Running periodic measurement...
\n
"
);
runner
.
enable_wall_time_stats
();
runner
.
pre_allocate_stats
();
// scheduler.get_profiler().disable_memory_measure();
runner
.
run_iterations
(
1
,
[
&
]()
{
runner
.
run_periodic
(
settings
.
iterations_
,
settings
.
interval_period_
,
settings
.
interval_deadline_
,
[
&
]()
{
scheduler
.
perform_work
([
&
]()
{
unbalanced_tree_search
(
unbalanced
::
SEED
,
unbalanced
::
ROOT_CHILDREN
,
unbalanced
::
Q
,
unbalanced
::
NORMAL_CHILDREN
);
});
},
0
);
// scheduler.get_profiler().current_run().print_dag(std::cout);
// scheduler.get_profiler().current_run().print_stats();
});
runner
.
commit_results
(
true
);
}
}
//int main() {
// PROFILE_ENABLE
// pls::malloc_scheduler_memory my_scheduler_memory{8, 2u << 18};
// pls::scheduler scheduler{&my_scheduler_memory, 8};
//
// scheduler.perform_work([&] {
// PROFILE_MAIN_THREAD
// for (int i = 0; i < 50; i++) {
// PROFILE_WORK_BLOCK("Top Level")
// int result = unbalanced_tree_search(SEED, ROOT_CHILDREN, Q, NORMAL_CHILDREN);
// std::cout << result << std::endl;
// }
// });
//
// PROFILE_SAVE("test_profile.prof")
//}
This diff is collapsed.
Click to expand it.
extern/benchmark_runner/benchmark_runner.h
View file @
e2f584c4
...
...
@@ -12,6 +12,7 @@
#include <bits/stdc++.h>
#include <thread>
#include <map>
#include <time.h>
#include <tuple>
#include <unistd.h>
...
...
@@ -35,6 +36,12 @@ class benchmark_runner {
unsigned
long
memory_pre_run_
;
unsigned
long
memory_post_run_
;
bool
wall_time_enabled_
{
false
};
const
string
WALL_TIME_PRE_RUN
=
"wall_time_pre_run_us"
;
const
string
WALL_TIME_POST_RUN
=
"wall_time_post_run_us"
;
unsigned
long
wall_time_pre_run_
;
unsigned
long
wall_time_post_run_
;
map
<
string
,
vector
<
long
>>
custom_stats_
;
void
print_statistics
()
{
...
...
@@ -108,6 +115,12 @@ class benchmark_runner {
add_custom_stats_field
(
MEMORY_POST_RUN
);
}
void
enable_wall_time_stats
()
{
wall_time_enabled_
=
true
;
add_custom_stats_field
(
WALL_TIME_PRE_RUN
);
add_custom_stats_field
(
WALL_TIME_POST_RUN
);
}
void
pre_allocate_stats
(
size_t
num
=
100000
)
{
times_
.
reserve
(
num
);
memset
(
times_
.
data
(),
'a'
,
num
*
sizeof
(
long
));
...
...
@@ -117,16 +130,54 @@ class benchmark_runner {
}
}
static
void
read_args
(
int
argc
,
char
**
argv
,
int
&
num_threads
,
string
&
path
)
{
if
(
argc
<
3
)
{
cout
<<
"Must Specifiy concurrency and output directory! (usage: `benchmark <output_directory> <num_threads>`)"
<<
endl
;
struct
benchmark_settings
{
enum
TYPE
{
ISOLATED
,
PERIODIC
};
string
output_directory_
;
size_t
size_
;
unsigned
num_threads_
;
TYPE
type_
;
size_t
iterations_
;
unsigned
long
interval_period_
;
unsigned
long
interval_deadline_
;
};
static
benchmark_settings
parse_parameters
(
int
argc
,
char
**
argv
)
{
benchmark_settings
result
;
string
tmp
;
if
(
argc
!=
5
&&
argc
!=
7
)
{
printf
(
"usage 1: `benchmark <output_directory> <size> <num_threads> <iterations>`
\n
"
);
printf
(
"usage 2: `benchmark <output_directory> <size> <num_threads> <iterations> <period> <deadline>`
\n
"
);
exit
(
1
);
}
string
tmp
=
argv
[
1
];
path
=
tmp
;
num_threads
=
atoi
(
argv
[
2
]);
result
.
output_directory_
=
argv
[
1
];
tmp
=
argv
[
2
];
result
.
size_
=
std
::
stoi
(
tmp
);
tmp
=
argv
[
3
];
result
.
num_threads_
=
std
::
stoi
(
tmp
);
if
(
argc
==
5
)
{
result
.
type_
=
benchmark_settings
::
ISOLATED
;
tmp
=
argv
[
4
];
result
.
iterations_
=
std
::
stoi
(
tmp
);
}
else
{
result
.
type_
=
benchmark_settings
::
PERIODIC
;
tmp
=
argv
[
4
];
result
.
iterations_
=
std
::
stoi
(
tmp
);
tmp
=
argv
[
5
];
result
.
interval_period_
=
std
::
stoi
(
tmp
);
tmp
=
argv
[
6
];
result
.
interval_deadline_
=
std
::
stoi
(
tmp
);
}
return
result
;
}
void
start_iteration
()
{
...
...
@@ -134,6 +185,11 @@ class benchmark_runner {
auto
memory_stats
=
query_process_memory_pages
();
memory_pre_run_
=
memory_stats
.
first
;
}
if
(
wall_time_enabled_
)
{
wall_time_pre_run_
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
microseconds
>
(
std
::
chrono
::
time_point_cast
<
std
::
chrono
::
microseconds
>
(
std
::
chrono
::
system_clock
::
now
()).
time_since_epoch
()).
count
();
}
last_start_time_
=
chrono
::
steady_clock
::
now
();
}
...
...
@@ -155,6 +211,13 @@ class benchmark_runner {
custom_stats_
[
MEMORY_PRE_RUN
][
iteration_index
]
=
memory_pre_run_
;
custom_stats_
[
MEMORY_POST_RUN
][
iteration_index
]
=
memory_post_run_
;
}
if
(
wall_time_enabled_
)
{
wall_time_post_run_
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
microseconds
>
(
std
::
chrono
::
time_point_cast
<
std
::
chrono
::
microseconds
>
(
std
::
chrono
::
system_clock
::
now
()).
time_since_epoch
()).
count
();
custom_stats_
[
WALL_TIME_PRE_RUN
][
iteration_index
]
=
wall_time_pre_run_
;
custom_stats_
[
WALL_TIME_POST_RUN
][
iteration_index
]
=
wall_time_post_run_
;
}
}
void
store_custom_stat
(
const
string
&
name
,
long
value
)
{
...
...
@@ -164,14 +227,8 @@ class benchmark_runner {
void
run_iterations
(
int
count
,
const
function
<
void
(
void
)
>
measure
,
int
warmup_count
,
const
function
<
void
(
void
)
>
prepare
=
[]()
{},
const
function
<
void
(
void
)
>
finish
=
[]()
{})
{
for
(
int
i
=
0
;
i
<
warmup_count
;
i
++
)
{
prepare
();
measure
();
}
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
using
namespace
std
::
literals
;
this_thread
::
sleep_for
(
100u
s
);
...
...
@@ -183,6 +240,90 @@ class benchmark_runner {
}
}
void
add_to_timespec
(
timespec
&
timespec
,
size_t
seconds
,
size_t
nanoseconds
)
{
timespec
.
tv_sec
+=
seconds
;
timespec
.
tv_nsec
+=
nanoseconds
;
while
(
timespec
.
tv_nsec
>
1000l
*
1000l
*
1000l
)
{
timespec
.
tv_nsec
-=
1000l
*
1000l
*
1000l
;
timespec
.
tv_sec
++
;
}
}
void
run_periodic
(
size_t
count
,
size_t
period_us
,
size_t
deadline_us
,
const
function
<
void
(
void
)
>
measure
)
{
size_t
period_nanoseconds
=
1000lu
*
period_us
;
size_t
period_seconds
=
period_nanoseconds
/
(
1000lu
*
1000lu
*
1000lu
);
period_nanoseconds
=
period_nanoseconds
-
period_seconds
*
1000lu
*
1000lu
*
1000lu
;
size_t
deadline_nanoseconds
=
1000lu
*
deadline_us
;
size_t
deadline_seconds
=
deadline_nanoseconds
/
(
1000lu
*
1000lu
*
1000lu
);
deadline_nanoseconds
=
deadline_nanoseconds
-
deadline_seconds
*
1000lu
*
1000lu
*
1000lu
;
// Prepare basic time spec for first iteration
timespec
iteration_start
,
iteration_end
,
deadline_end
,
finish_time
;
if
(
clock_gettime
(
CLOCK_MONOTONIC
,
&
iteration_start
)
==
-
1
)
{
perror
(
"clock_gettime"
);
exit
(
1
);
}
add_to_timespec
(
iteration_start
,
period_seconds
,
period_nanoseconds
);
size_t
current_iteration
=
0
;
while
(
current_iteration
<
count
)
{
// Sleep until the next iteration
long
sleep_error
=
clock_nanosleep
(
CLOCK_MONOTONIC
,
TIMER_ABSTIME
,
&
iteration_start
,
nullptr
);
if
(
sleep_error
)
{
printf
(
"Sleep Error %ld
\n
"
,
sleep_error
);
}
// Invoke iteration
start_iteration
();
measure
();
end_iteration
();
// Calculate all relevant time points for this iteration
if
(
clock_gettime
(
CLOCK_MONOTONIC
,
&
finish_time
)
==
-
1
)
{
perror
(
"clock_gettime"
);
exit
(
1
);
}
iteration_end
=
iteration_start
;
add_to_timespec
(
iteration_end
,
period_seconds
,
period_nanoseconds
);
deadline_end
=
iteration_start
;
add_to_timespec
(
deadline_end
,
deadline_seconds
,
deadline_nanoseconds
);
// Store 'actual' wall time instead of iteration time (we want to include sleeping here!)
long
wall_time_us
=
0
;
wall_time_us
+=
(
finish_time
.
tv_sec
-
iteration_start
.
tv_sec
)
*
1000l
*
1000l
;
wall_time_us
+=
((
long
)
finish_time
.
tv_nsec
-
(
long
)
iteration_start
.
tv_nsec
)
/
1000l
;
printf
(
"Difference: %d
\n
"
,
wall_time_us
-
times_
[
current_iteration
]);
times_
[
current_iteration
]
=
wall_time_us
;
if
(
finish_time
.
tv_sec
>=
deadline_end
.
tv_sec
&&
finish_time
.
tv_nsec
>
deadline_end
.
tv_nsec
)
{
printf
(
"Deadline Miss!
\n
"
);
// TODO: Remove
}
// Skip iterations if their start time is later than the current time (skipping)
while
(
finish_time
.
tv_sec
>=
iteration_end
.
tv_sec
&&
finish_time
.
tv_nsec
>
iteration_end
.
tv_nsec
)
{
iteration_start
=
iteration_end
;
iteration_end
=
iteration_start
;
add_to_timespec
(
iteration_end
,
period_seconds
,
period_nanoseconds
);
current_iteration
++
;
start_iteration
();
end_iteration
();
times_
[
current_iteration
]
=
0
;
}
// Progress to next iteration (normally)
current_iteration
++
;
iteration_start
=
iteration_end
;
}
}
void
commit_results
(
bool
print_stats
)
{
if
(
print_stats
)
{
print_statistics
();
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment