\(\newcommand{\W}[1]{ \; #1 \; }\) \(\newcommand{\R}[1]{ {\rm #1} }\) \(\newcommand{\B}[1]{ {\bf #1} }\) \(\newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} }\) \(\newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} }\) \(\newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} }\) \(\newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }\)
harmonic_time¶
View page sourceTiming Test of Multi-Threaded Summation of 1/i¶
Syntax¶
harmonic_time
(Purpose¶
Runs a correctness and timing test for a multi-threaded computation of the summation that defines the harmonic series
Thread¶
It is assumed that this function is called by thread zero in sequential mode; i.e., not in_parallel .
ok¶
This return value has prototype
bool
ok
If it is true,
harmonic_time
passed the correctness test.
Otherwise it is false.
time_out¶
This argument has prototype
double&
time_out
The input value of the argument does not matter. Upon return it is the number of wall clock seconds required for to compute the summation.
test_time¶
Is the minimum amount of wall clock time that the test should take. The number of repeats for the test will be increased until this time is reached. The reported time_out is the total wall clock time divided by the number of repeats.
num_threads¶
This argument has prototype
size_t
num_threads
It specifies the number of threads that are available for this test. If it is zero, the test is run without the multi-threading environment and
1 ==
thread_alloc::num_threads
()
when harmonic_time
is called.
If it is non-zero, the test is run with the multi-threading and
num_threads =
thread_alloc::num_threads
()
when harmonic_time
is called.
mega_sum¶
This argument has prototype
size_t&
mega_sum
and is greater than zero. The value \(n\) in the summation is equal to \(10^6\) times mega_sum .
Source¶
# include <cstring>
# include <limits>
# include <iostream>
# include <cstdlib>
# include <algorithm>
// Note there is no mention of parallel mode in the documentation for
// speed_test (so it is safe to use without special consideration).
# include <cppad/utility/time_test.hpp>
namespace {
// value of sum resulting from most recent call to test_once
double sum_ = 0.;
//
void test_once(void)
{ if( mega_sum_ < 1 )
{ std::cerr << "harmonic_time: mega_sum < 1" << std::endl;
exit(1);
}
size_t num_sum = mega_sum_ * 1000000;
bool ok = harmonic_sum(sum_, num_sum);
if( ! ok )
{ std::cerr << "harmonic: error" << std::endl;
exit(1);
}
return;
}
//
void test_repeat(size_t repeat)
{ size_t i;
for(i = 0; i < repeat; i++)
test_once();
return;
}
}
// This is the only routine that is accessible outside of this file
bool harmonic_time(
double& time_out, double test_time, size_t num_threads, size_t mega_sum)
{ bool ok = true;
ok &= thread_alloc::thread_num() == 0;
// arguments passed to harmonic_sum
num_threads_ = num_threads;
mega_sum_ = mega_sum;
// create team of threads
ok &= thread_alloc::in_parallel() == false;
if( num_threads > 0 )
{ team_create(num_threads);
ok &= num_threads == thread_alloc::num_threads();
}
else
{ ok &= 1 == thread_alloc::num_threads();
}
// run the test case and set the time return value
time_out = CppAD::time_test(test_repeat, test_time);
// destroy team of threads
if( num_threads > 0 )
team_destroy();
ok &= thread_alloc::in_parallel() == false;
// Correctness check
double eps1000 =
double(mega_sum_) * 1e3 * std::numeric_limits<double>::epsilon();
size_t i = mega_sum_ * 1000000;
double check = 0.;
while(i)
check += 1. / double(i--);
ok &= std::fabs(sum_ - check) <= eps1000;
return ok;
}