source: trunk/ADOL-C/src/storemanager.h @ 198

Last change on this file since 198 was 198, checked in by kulshres, 8 years ago

move around some of Johannes Willkomm's code

Bring the code in tape_handling.cpp leaving only the declaration
in header. Make the StoreManager? the default. Remove old next_loc
and add free_loc without the new_ prefix. Add the header file to
Makefile.am in order for it to be distributed.

Signed-off-by: Kshitij Kulshreshtha <kshitij@…>

File size: 6.0 KB
Line 
1// -*- c++ -*- hello emacs...
2/*----------------------------------------------------------------------------
3 ADOL-C--  Automatic Differentiation by Overloading in C++ - simplified
4 File:     storemanager.h
5 Revision: $Id$
6 Contents: storemanager.h contains definitions of abstract interface
7           class StoreManager and some derived classes implementing the
8           desired functionality.
9
10 Copyright (c) 2006 Johannes Willkomm <johannes.willkomm@rwth-aachen.de>
11 Written by Johannes Willkomm <johannes.willkomm@rwth-aachen.de>
12 
13 This file is part of ADOL-C.
14
15 The classes StoreManagerXYZ basically takes the global double *store pointer
16 into their obhut and implement next_loc and free_loc.
17
18 They basic idea is taken from "The C++ Programming Language" by Bjarne
19 Stroustrup, from the chapter 19 on iterators and allocators.
20
21 To understand how and why they work do the following:
22 1) Have a look at StoreManagerInSitu and convince yourself that it is
23    exactly the same as the solution presented in the Stroustrup book,
24    except that we always have just one big array instead of a linked
25    list of chunks.
26
27    This means in particular that we have to copy the values from the
28    old array into the lower half of the new one (we always double the size).
29
30 2) Have a look at StoreManagerLocint and convince yourself that these do
31    the same as StoreManagerInSitu except that the linked list of free
32    slots is maintained in a completely different portion of memory. This
33    means the values in freed slots remain untouched until they are
34    allocated again.
35
36
37
38 class StoreManagerInSitu
39 An unsafe implementation is provided as well, but commented out.
40 It does not use the indexFeld array which saves between
41 25% and 50% memory relative to the above safe implementation.
42
43 It is most closely modelled after the example found in the
44 Stroustrup book.
45
46 It appears that it works very well, if one does not use the
47 trace_on(tag, 1); ... trace_off(); reverse(); way of using ADOL-C.
48 If the first sweep is forward it works fine.
49 Therefore I left it in here as a comment so an interested user
50 with acute main memory scarcity may give it a try.
51           
52
53 History:
54          20110208 kk:     incorporated in ADOL-C; moved some code arround
55          20060507 jw:     begin
56
57----------------------------------------------------------------------------*/
58
59#ifndef ADOL_C__STOREMANAGER_H
60#define ADOL_C__STOREMANAGER_H
61
62#include <adolc/common.h>
63
64class StoreManager {
65protected:
66  static size_t const initialeGroesse = 4;
67public:
68  virtual ~StoreManager() {}
69
70  virtual locint next_loc() = 0;
71  virtual void free_loc(locint) = 0;
72
73//   // effectively the current size of the store array
74  virtual size_t maxSize() const = 0;
75
76//   // the number of slots currently in use
77  virtual size_t size() const = 0;
78};
79
80
81
82class StoreManagerLocint : public StoreManager {
83protected:
84  double * &storePtr;
85  locint * indexFeld;
86  locint head;
87  size_t &groesse;
88  size_t anzahl;
89private:
90  void grow();
91public:
92
93  StoreManagerLocint(double * &storePtr, size_t &size);
94
95  virtual ~StoreManagerLocint();
96  virtual inline size_t size() const { return anzahl; }
97
98  virtual inline size_t maxSize() const { return groesse; }
99
100  virtual inline bool realloc_on_next_loc() const { 
101      return (head == 0);
102  }
103
104  virtual locint next_loc();
105  virtual void free_loc(locint loc); 
106};
107
108#if 0
109/* This implementation is unsafe in that using tace_on with keep=1 and
110   reverse mode directly afterwards will yield incorrect results.
111   For all other purposes it seem to work just fine, so it's left here
112   for reference as a comment.
113*/
114
115/* unsafe - use with care */
116
117class StoreManagerInSitu : public StoreManager {
118  //  static size_t const initialeGroesse = 512;
119protected:
120  double * &storePtr;
121  struct Link {
122    struct Link *next;
123  };
124  Link *head;
125  size_t groesse;
126  size_t anzahl;
127public:
128  size_t maxIndexUsed;
129
130  StoreManager(double * &storePtr) :
131    storePtr(storePtr),
132    head(0),
133    groesse(initialeGroesse),
134    anzahl(0),
135    maxIndexUsed(0)
136  {
137    // while a place in store is unused we want to place
138    // a Link stucture (i.e. a pointer) there
139    assert(sizeof(double) >= sizeof(void*));
140    assert(sizeof(double) >= sizeof(Link));
141    std::cerr << "StoreManager::StoreManager()\n";
142  }
143
144  virtual ~StoreManager() {
145    if (storePtr) {
146      delete [] storePtr;
147      storePtr = 0;
148    }
149    std::cerr << "StoreManager::~StoreManager()\n";
150  }
151
152  virtual inline size_t size() const { return anzahl; }
153
154  virtual inline size_t maxSize() const { return groesse; }
155
156  virtual locint next_loc(size_t n = 1) {
157    assert(n == 1);
158    if (head == 0) {
159      grow();
160    }
161    assert(head);
162    double * const dPtr = reinterpret_cast<double*>(head);
163    head = head->next;
164    ++anzahl;
165    locint const result = dPtr - storePtr;
166    maxIndexUsed = std::max((locint)maxIndexUsed, result);
167    return result;
168  }
169
170  virtual void free_loc(locint loc) {
171    assert(loc < groesse);
172    Link *returned = reinterpret_cast<Link*>(storePtr + loc);
173    returned->next = head;
174    head = returned;
175    --anzahl;
176  }
177private:
178  void grow() {
179    size_t const alteGroesse = groesse;
180    groesse *= 2;
181    assert(alteGroesse == initialeGroesse or size() == alteGroesse);
182    std::cerr << "StoreManager::grow(): increase size to " << groesse << "\n";
183    double *const oldStore = storePtr;
184    std::cerr << "StoreManager::grow(): allocate " << groesse * sizeof(double) << " B\n";
185    storePtr = new double[groesse];
186    size_t i = 0;
187    if (alteGroesse != initialeGroesse) { // nicht beim ersten Mal
188      std::cerr << "StoreManager::grow(): copy values\n";
189      for ( ; i < alteGroesse; ++i) {
190        storePtr[i] = oldStore[i];
191      }
192      std::cerr << "StoreManager::grow(): free " << alteGroesse * sizeof(double) << " B\n";
193      delete [] oldStore;
194    }
195    head = reinterpret_cast<Link*>(storePtr + i);
196    for ( ; i < groesse-1; ++i) {
197      reinterpret_cast<Link*>(storePtr + i)->next
198        = reinterpret_cast<Link*>(storePtr + i + 1);
199    }
200    reinterpret_cast<Link*>(storePtr + i)->next = 0;
201  }
202
203};
204#endif /* 0 */
205
206#endif /* ADOL_C__STOREMANAGER_H */
207
Note: See TracBrowser for help on using the repository browser.