Prev Next team_example.cpp

@(@\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}} }@)@This is cppad-20221105 documentation. Here is a link to its current documentation .
Using a Team of AD Threads: Example and Test

Purpose
This example demonstrates how use a team of threads with CppAD.

thread_team
The following three implementations of the team_thread.hpp specifications are included:
team_openmp.cpp OpenMP Implementation of a Team of AD Threads
team_bthread.cpp Boost Thread Implementation of a Team of AD Threads
team_pthread.cpp Pthread Implementation of a Team of AD Threads

Source Code

# include <cppad/cppad.hpp>
# include "team_thread.hpp"
# define NUMBER_THREADS  4

namespace {
    using CppAD::thread_alloc;

    // structure with information for one thread
    typedef struct {
        // function argument (worker input)
        double          x;
        // false if an error occurs, true otherwise (worker output)
        bool            ok;
    } work_one_t;
    // vector with information for all threads
    // (use pointers instead of values to avoid false sharing)
    work_one_t* work_all_[NUMBER_THREADS];
    // --------------------------------------------------------------------
    // function that does the work for one thread
    void worker(void)
    {   using CppAD::NearEqual;
        using CppAD::AD;
        bool ok = true;
        size_t thread_num = thread_alloc::thread_num();

        // CppAD::vector uses the CppAD fast multi-threading allocator
        CppAD::vector< AD<double> > ax(1), ay(1);
        ax[0] = work_all_[thread_num]->x;
        Independent(ax);
        ay[0] = sqrt( ax[0] * ax[0] );
        CppAD::ADFun<double> f(ax, ay);

        // Check function value corresponds to the identity
        double eps = 10. * CppAD::numeric_limits<double>::epsilon();
        ok        &= NearEqual(ay[0], ax[0], eps, eps);

        // Check derivative value corresponds to the identity.
        CppAD::vector<double> d_x(1), d_y(1);
        d_x[0] = 1.;
        d_y    = f.Forward(1, d_x);
        ok    &= NearEqual(d_x[0], 1., eps, eps);

        // pass back ok information for this thread
        work_all_[thread_num]->ok = ok;
    }
}

// This test routine is only called by the master thread (thread_num = 0).
bool team_example(void)
{   bool ok = true;

    size_t num_threads = NUMBER_THREADS;

    // Check that no memory is in use or avialable at start
    // (using thread_alloc in sequential mode)
    size_t thread_num;
    for(thread_num = 0; thread_num < num_threads; thread_num++)
    {   ok &= thread_alloc::inuse(thread_num) == 0;
        ok &= thread_alloc::available(thread_num) == 0;
    }

    // initialize work_all_
    for(thread_num = 0; thread_num < num_threads; thread_num++)
    {   // allocate separate memory for this thread to avoid false sharing
        size_t min_bytes(sizeof(work_one_t)), cap_bytes;
        void*  v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);
        work_all_[thread_num]     = static_cast<work_one_t*>(v_ptr);
        // in case this thread's worker does not get called
        work_all_[thread_num]->ok = false;
        // parameter that defines the work for this thread
        work_all_[thread_num]->x  = double(thread_num) + 1.;
    }

    ok &= team_create(num_threads);
    ok &= team_work(worker);
    ok &= team_destroy();

    // go down so that free memrory for other threads before memory for master
    thread_num = num_threads;
    while(thread_num--)
    {   // check that this thread was ok with the work it did
        ok &= work_all_[thread_num]->ok;
        // delete problem specific information
        void* v_ptr = static_cast<void*>( work_all_[thread_num] );
        thread_alloc::return_memory( v_ptr );
        // check that there is no longer any memory inuse by this thread
        // (for general applications, the master might still be using memory)
        ok &= thread_alloc::inuse(thread_num) == 0;
        // return all memory being held for future use by this thread
        thread_alloc::free_available(thread_num);
    }
    return ok;
}

Input File: example/multi_thread/team_example.cpp