|
| 1 | +#!/home/chrisarg/perl5/perlbrew/perls/current/bin/perl |
| 2 | +use v5.36; |
| 3 | + |
| 4 | +use List::Util qw(sum); |
| 5 | +use Benchmark::CSV; |
| 6 | +use PDL::Lite; |
| 7 | +use PDL::NiceSlice; |
| 8 | +use PDL::IO::Misc; |
| 9 | +use PDL::IO::CSV ':all'; |
| 10 | +use PDL::Stats::Basic; |
| 11 | +use Time::HiRes qw(time); |
| 12 | +use OpenMP::Environment; |
| 13 | +use Inline ( |
| 14 | + C => 'DATA', |
| 15 | + ccflagsex => q{-fopenmp}, |
| 16 | + lddlflags => join( q{ }, $Config::Config{lddlflags}, q{-fopenmp} ), |
| 17 | + myextlib => '' |
| 18 | +); |
| 19 | + |
| 20 | +my $openmp_env = OpenMP::Environment->new; |
| 21 | +$openmp_env->omp_num_threads(16); |
| 22 | + |
| 23 | +my $benchmark = Benchmark::CSV->new( |
| 24 | + output => './addArrayofIntegers.csv', |
| 25 | + sample_size => 1, |
| 26 | +); |
| 27 | + |
| 28 | +my $num_elements = 1_000_003; |
| 29 | + |
| 30 | +## Create an array of $num_elements random integers, between -100, 100 |
| 31 | +my @array = map { int( rand(200) ) - 100 } 1 .. $num_elements; |
| 32 | +my $array_double_ASM = pack "d*", @array; |
| 33 | + |
| 34 | + |
| 35 | +say "Starting benchmark"; |
| 36 | +$benchmark->add_instance( |
| 37 | + 'C_SIMD_wo_alloc' => sub { |
| 38 | + sum_array_SIMD_C( $array_double_ASM, scalar @array ); |
| 39 | + }, |
| 40 | +); |
| 41 | +$benchmark->add_instance( |
| 42 | + 'C_SIMD_w_alloc' => sub { |
| 43 | + my $array_double_ASM = pack "d*", @array; |
| 44 | + sum_array_SIMD_C( $array_double_ASM, scalar @array ); |
| 45 | + }, |
| 46 | +); |
| 47 | +$benchmark->add_instance( |
| 48 | + 'C_SIMD_OMP_wo_alloc' => sub { |
| 49 | + sum_array_SIMD_OMP_C( $array_double_ASM, scalar @array ); |
| 50 | + }, |
| 51 | +); |
| 52 | +$benchmark->add_instance( |
| 53 | + 'C_SIMD_OMP_w_alloc' => sub { |
| 54 | + my $array_double_ASM = pack "d*", @array; |
| 55 | + sum_array_SIMD_OMP_C( $array_double_ASM, scalar @array ); |
| 56 | + }, |
| 57 | +); |
| 58 | + |
| 59 | +$benchmark->add_instance( |
| 60 | + 'C_OMP_wo_alloc' => sub { |
| 61 | + sum_array_OMP_C( $array_double_ASM, scalar @array ); |
| 62 | + }, |
| 63 | +); |
| 64 | +$benchmark->add_instance( |
| 65 | + 'C_OMP_w_alloc' => sub { |
| 66 | + my $array_double_ASM = pack "d*", @array; |
| 67 | + sum_array_OMP_C( $array_double_ASM, scalar @array ); |
| 68 | + }, |
| 69 | +); |
| 70 | + |
| 71 | +$benchmark->run_iterations(1000); |
| 72 | + |
| 73 | +# Load the CSV file |
| 74 | + |
| 75 | +my @data = rcsv1D( 'addArrayofIntegers.csv', { text2bad => 1, header => 1 } ); |
| 76 | + |
| 77 | +my %summary_stats = (); |
| 78 | + |
| 79 | +foreach my $col ( 0 .. $#data ) { |
| 80 | + my $pdl = pdl( $data[$col] ); |
| 81 | + my $mean = $pdl->average; |
| 82 | + my $stddev = $pdl->stdv_unbiased; |
| 83 | + my $median = $pdl->median; |
| 84 | + $summary_stats{ $data[$col]->hdr->{col_name} } = |
| 85 | + { mean => $mean, stddev => $stddev, median => $median }; |
| 86 | +} |
| 87 | + |
| 88 | +# Get the column names from the first row |
| 89 | +my @column_names = sort keys %{ $summary_stats{ ( keys %summary_stats )[0] } }; |
| 90 | + |
| 91 | +# Define the width for each column |
| 92 | +my $width_name = 24; |
| 93 | +my $width_col = 10; |
| 94 | + |
| 95 | +# Print the column names |
| 96 | +printf "%-${width_name}s", ''; |
| 97 | +printf "%${width_col}s", $_ for @column_names; |
| 98 | +print "\n"; |
| 99 | + |
| 100 | +# Print each row |
| 101 | +foreach my $row_name ( sort keys %summary_stats ) { |
| 102 | + printf "%-${width_name}s", $row_name; |
| 103 | + printf "%${width_col}.1e", $summary_stats{$row_name}{$_} for @column_names; |
| 104 | + print "\n"; |
| 105 | +} |
| 106 | + |
| 107 | +unlink 'addArrayofIntegers.csv'; |
| 108 | +## load the CSV file and print a summary of the results using PDL |
| 109 | + |
| 110 | +__DATA__ |
| 111 | +__C__ |
| 112 | +#include <omp.h> |
| 113 | +
|
| 114 | +
|
| 115 | +
|
| 116 | +
|
| 117 | +void _ENV_set_num_threads() { |
| 118 | + char *num; |
| 119 | + num = getenv("OMP_NUM_THREADS"); |
| 120 | + omp_set_num_threads(atoi(num)); |
| 121 | +} |
| 122 | +
|
| 123 | +
|
| 124 | +double sum_array_SIMD_C(char *array_in, size_t length) { |
| 125 | + double sum = 0.0; |
| 126 | + double * array = (double *) array_in; |
| 127 | + #pragma omp simd reduction(+:sum) |
| 128 | + for (size_t i = 0; i < length; i++) { |
| 129 | + sum += array[i]; |
| 130 | + } |
| 131 | + return sum; |
| 132 | +} |
| 133 | +
|
| 134 | +double sum_array_SIMD_OMP_C(char *array_in, size_t length) { |
| 135 | + double sum = 0.0; |
| 136 | + double * array = (double *) array_in; |
| 137 | + _ENV_set_num_threads(); |
| 138 | + #pragma omp parallel for simd reduction(+:sum) schedule(static,8) |
| 139 | + for (size_t i = 0; i < length; i++) { |
| 140 | + sum += array[i]; |
| 141 | + } |
| 142 | + return sum; |
| 143 | +} |
| 144 | +
|
| 145 | +double sum_array_OMP_C(char *array_in, size_t length) { |
| 146 | + double sum = 0.0; |
| 147 | + double * array = (double *) array_in; |
| 148 | + _ENV_set_num_threads(); |
| 149 | + #pragma omp parallel for reduction(+:sum) schedule(static,8) |
| 150 | + for (size_t i = 0; i < length; i++) { |
| 151 | + sum += array[i]; |
| 152 | + } |
| 153 | + return sum; |
| 154 | +} |
0 commit comments