source: branches/cache/cppad/local/cache.hpp @ 3335

Last change on this file since 3335 was 3335, checked in by bradbell, 6 years ago
  1. cache.sh should not revert sweep files that have changed.
  2. Fix calls that were erased by mistake fixed in 1.
  3. Use cache2var (better description than cache).
  4. Put cache2var in ADFun function object.
  • Property svn:keywords set to Id
File size: 3.9 KB
Line 
1/*
2$begin cache$$
3
4$section Under Construction$$
5
6$end
7*/
8# include <list>
9
10namespace CppAD { // BEGIN_CPPAD_NAMESPACE
11
12template <class Base>
13void create_cache(
14        player<Base>&       play         ,
15        CppAD::vector<addr_t>& var2cache )
16{       size_t i, j, k;
17
18        // number of variables in operation sequence
19        size_t num_var = play.num_var_rec();
20
21        // initialize last use for each variable as the beginning of the
22        // operation sequence
23        CppAD::vector<size_t> last_use(num_var);
24        for(i = 0; i < num_var; i++)
25                last_use[i] = i;
26
27        // index of last result for current user atomic operation
28        size_t user_i_var;
29        bool   in_user_atomic = false;
30
31        // variables used to represent one operation
32        OpCode        op;     // operator
33        const addr_t* arg;    // arguments
34        size_t        i_var;  // index of last result for operation
35        size_t        i_op;   // index of operation
36
37        // Initilalize forward mode sweep through the operation sequence
38        play.forward_start(op, arg, i_op, i_var);
39        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
40
41        while( op != EndOp )
42        {       // next op
43                play.forward_next(op, arg, i_op, i_var);
44                CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var);
45
46                if( op == UserOp )
47                {       in_user_atomic = ! in_user_atomic;
48                        if( in_user_atomic )
49                                user_i_var     = i_var + size_t( arg[3] );
50                        else
51                                user_i_var     = i_var;
52                }
53                //
54                size_t n_arg = NumArg(op);
55                for(size_t i_arg = 0; i_arg < n_arg; i_arg++)
56                {       if( arg_is_variable(op, arg, i_arg) )
57                                last_use[ arg[i_arg] ] = i_var;
58                }
59        }
60
61        // sort the order of the last_use elements
62        CppAD::vector<size_t> order(num_var);
63        index_sort(last_use, order);
64
65        // initialize the cache vector and available flags as empty
66        var2cache.resize(num_var);
67        std::list<addr_t> available;
68        std::list<addr_t>::iterator itr;
69
70        // compute the cache index corresponding to each variable index
71        size_t i_cache = num_var;
72        size_t i_last  = 0;
73        for(i_var = 0; i_var < num_var; i_var++)
74        {       if( available.empty() )
75                        available.push_front(i_cache++);
76                var2cache[i_var] = available.front();
77                available.pop_front();
78
79                while( i_last < num_var && last_use[ order[i_last] ] <= i_var )
80                {       available.push_back( var2cache[ order[i_last++] ] );
81                }
82        }
83
84        // temporary printing of result
85        std::cout << "i_var, last_use, cache" << std::endl;
86        for(i_var = 0; i_var < num_var; i_var++)
87        {       std::cout << i_var << ", ";
88                std::cout << last_use[i_var] << ", ";
89                std::cout << var2cache[i_var] << std::endl;
90        }
91        std::cout << "num_cache = " << i_cache - num_var << std::endl;
92
93
94        // 2DO: make rec an argument
95        recorder<Base> rec;
96        rec.free();
97
98        // Copy parameters to new recording
99        size_t num_par = play.num_par_rec();
100        for(i = 0; i < num_par; i++)
101                rec.PutPar( play.GetPar(i) );
102
103        // Copy VecAD indices in to new recording
104        size_t num_vecad_vec = play.num_vecad_vec_rec();
105        j                    = 0;
106        for(i = 0; i < num_vecad_vec; i++)
107        {       // lenght of the VecAD object
108                size_t length = play.GetVecInd(j);
109                for(k = 1; k <= length; k++)
110                        rec.PutVecInd( play.GetVecInd(j+k)  );
111                // start of the next VecAD entry
112                j += length + 1;
113        }
114        CPPAD_ASSERT_UNKNOWN( j == play.num_vec_ind_rec() );
115
116        // Initilalize forward sweep through the operation sequence
117        play.forward_start(op, arg, i_op, i_var);
118        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
119
120        // playing forward skips BeginOp at the beginning, but not EndOp at
121        // the end.  Put BeginOp at beginning of recording
122        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
123        CPPAD_ASSERT_NARG_NRES(BeginOp, 1, 1);
124        rec.PutOp(BeginOp);
125        rec.PutArg(0);
126
127        while( op != EndOp )
128        {       // next op
129                play.forward_next(op, arg, i_op, i_var);
130                CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var);
131
132                rec.PutOp(op);
133                //
134                size_t n_arg = NumArg(op);
135                for(size_t i_arg = 0; i_arg < n_arg; i_arg++)
136                {       if( arg_is_variable(op, arg, i_arg) )
137                                rec.PutArg( var2cache[ arg[i_arg] ] );
138                        else
139                                rec.PutArg( arg[i_arg] );
140                }
141        }
142        return;
143}
144
145
146template <class Base>
147void ADFun<Base>::cache(void)
148{       create_cache(play_, var2cache_);
149}
150
151} // END_CPPAD_NAMESPACE
Note: See TracBrowser for help on using the repository browser.