Skip to content

Commit 041dc9a

Browse files
committed
PWR081: Add benchmark
1 parent e6ec687 commit 041dc9a

4 files changed

Lines changed: 105 additions & 0 deletions

File tree

Benchmark/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ if (OCB_Fortran_COMPILER_ID STREQUAL "GNU")
2020
endif()
2121
add_benchmark(PWR079)
2222
add_benchmark(PWR080)
23+
add_benchmark(PWR081)

Benchmark/src/PWR081.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "Benchmark.h"
2+
3+
// Forward-declare the functions to benchmark
4+
extern "C" {
5+
double compute_stats_f(const int n, const double *data, double *mean,
6+
double *stddev);
7+
double compute_stats_improved_f(const int n, const double *data, double *mean,
8+
double *stddev);
9+
}
10+
11+
// Size adjusted to fit execution on micro-seconds
12+
constexpr int N = 1024 * 1024;
13+
14+
#if OCB_ENABLE_Fortran
15+
16+
static void FortranExampleBench(benchmark::State &state) {
17+
auto array = OpenCatalog::CreateRandomVector<double>(N);
18+
19+
for (auto _ : state) {
20+
double mean, stddev;
21+
compute_stats_f(N, array.data(), &mean, &stddev);
22+
benchmark::DoNotOptimize(mean);
23+
benchmark::DoNotOptimize(stddev);
24+
}
25+
}
26+
27+
static void FortranImprovedBench(benchmark::State &state) {
28+
auto array = OpenCatalog::CreateRandomVector<double>(N);
29+
30+
for (auto _ : state) {
31+
double mean, stddev;
32+
compute_stats_improved_f(N, array.data(), &mean, &stddev);
33+
benchmark::DoNotOptimize(mean);
34+
benchmark::DoNotOptimize(stddev);
35+
}
36+
}
37+
38+
// The goal of these benchmarks is to demonstrate that the suggested check does
39+
// not incur any performance penalty
40+
OC_BENCHMARK("PWR081 Fortran Example", FortranExampleBench);
41+
OC_BENCHMARK("PWR081 Fortran Improved", FortranImprovedBench);
42+
43+
#endif
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
! PWR081: Uninitialized output arguments can lead to undefined behavior
2+
3+
! NOT-PWR070: Explicit-shape arrays used for C-interoperability
4+
pure subroutine compute_stats_f(n, data, mean, stddev) bind(c)
5+
use iso_c_binding, only: c_double, c_int
6+
implicit none
7+
8+
integer(kind=c_int), intent(in), value :: n
9+
real(kind=c_double), dimension(n), intent(in) :: data
10+
real(kind=c_double), intent(out) :: mean
11+
real(kind=c_double), intent(out) :: stddev
12+
13+
integer(kind=c_int) :: i
14+
15+
! We can't compute stddev from a single data point
16+
if (n <= 1) then
17+
return
18+
end if
19+
20+
! Also abort if there are invalid data points
21+
do i = 1, n
22+
if (data(i) < -900.0) then
23+
return
24+
end if
25+
end do
26+
27+
mean = sum(data) / n
28+
stddev = sqrt(sum((data - mean)**2) / (n - 1))
29+
end subroutine compute_stats_f
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
! PWR081: Uninitialized output arguments can lead to undefined behavior
2+
3+
! NOT-PWR070: Explicit-shape arrays used for C-interoperability
4+
pure subroutine compute_stats_improved_f(n, data, mean, stddev) bind(c)
5+
use iso_c_binding, only: c_double, c_int
6+
implicit none
7+
8+
integer(kind=c_int), intent(in), value :: n
9+
real(kind=c_double), dimension(n), intent(in) :: data
10+
real(kind=c_double), intent(out) :: mean
11+
real(kind=c_double), intent(out) :: stddev
12+
13+
integer(kind=c_int) :: i
14+
15+
mean = 0.0
16+
stddev = 0.0
17+
18+
! We can't compute stddev from a single data point
19+
if (n <= 1) then
20+
return
21+
end if
22+
23+
! Also abort if there are invalid data points
24+
do i = 1, n
25+
if (data(i) < -900.0) then
26+
return
27+
end if
28+
end do
29+
30+
mean = sum(data) / n
31+
stddev = sqrt(sum((data - mean)**2) / (n - 1))
32+
end subroutine compute_stats_improved_f

0 commit comments

Comments
 (0)