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

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

allow openmp to work with the new memory manager

needs further testing to ensure consistency of derivatives

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

File size: 6.2 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, size_t &numlives);
94  StoreManagerLocint(const StoreManagerLocint *const stm, double * &storePtr, size_t &size, size_t &numLives);
95
96  virtual ~StoreManagerLocint();
97  virtual inline size_t size() const { return anzahl; }
98
99  virtual inline size_t maxSize() const { return groesse; }
100
101  virtual inline bool realloc_on_next_loc() const { 
102      return (head == 0);
103  }
104
105  virtual locint next_loc();
106  virtual void free_loc(locint loc); 
107};
108
109#if 0
110/* This implementation is unsafe in that using tace_on with keep=1 and
111   reverse mode directly afterwards will yield incorrect results.
112   For all other purposes it seem to work just fine, so it's left here
113   for reference as a comment.
114*/
115
116/* unsafe - use with care */
117
118class StoreManagerInSitu : public StoreManager {
119  //  static size_t const initialeGroesse = 512;
120protected:
121  double * &storePtr;
122  struct Link {
123    struct Link *next;
124  };
125  Link *head;
126  size_t groesse;
127  size_t anzahl;
128public:
129  size_t maxIndexUsed;
130
131  StoreManager(double * &storePtr) :
132    storePtr(storePtr),
133    head(0),
134    groesse(initialeGroesse),
135    anzahl(0),
136    maxIndexUsed(0)
137  {
138    // while a place in store is unused we want to place
139    // a Link stucture (i.e. a pointer) there
140    assert(sizeof(double) >= sizeof(void*));
141    assert(sizeof(double) >= sizeof(Link));
142    std::cerr << "StoreManager::StoreManager()\n";
143  }
144
145  virtual ~StoreManager() {
146    if (storePtr) {
147      delete [] storePtr;
148      storePtr = 0;
149    }
150    std::cerr << "StoreManager::~StoreManager()\n";
151  }
152
153  virtual inline size_t size() const { return anzahl; }
154
155  virtual inline size_t maxSize() const { return groesse; }
156
157  virtual locint next_loc(size_t n = 1) {
158    assert(n == 1);
159    if (head == 0) {
160      grow();
161    }
162    assert(head);
163    double * const dPtr = reinterpret_cast<double*>(head);
164    head = head->next;
165    ++anzahl;
166    locint const result = dPtr - storePtr;
167    maxIndexUsed = std::max((locint)maxIndexUsed, result);
168    return result;
169  }
170
171  virtual void free_loc(locint loc) {
172    assert(loc < groesse);
173    Link *returned = reinterpret_cast<Link*>(storePtr + loc);
174    returned->next = head;
175    head = returned;
176    --anzahl;
177  }
178private:
179  void grow() {
180    size_t const alteGroesse = groesse;
181    groesse *= 2;
182    assert(alteGroesse == initialeGroesse or size() == alteGroesse);
183    std::cerr << "StoreManager::grow(): increase size to " << groesse << "\n";
184    double *const oldStore = storePtr;
185    std::cerr << "StoreManager::grow(): allocate " << groesse * sizeof(double) << " B\n";
186    storePtr = new double[groesse];
187    size_t i = 0;
188    if (alteGroesse != initialeGroesse) { // nicht beim ersten Mal
189      std::cerr << "StoreManager::grow(): copy values\n";
190      for ( ; i < alteGroesse; ++i) {
191        storePtr[i] = oldStore[i];
192      }
193      std::cerr << "StoreManager::grow(): free " << alteGroesse * sizeof(double) << " B\n";
194      delete [] oldStore;
195    }
196    head = reinterpret_cast<Link*>(storePtr + i);
197    for ( ; i < groesse-1; ++i) {
198      reinterpret_cast<Link*>(storePtr + i)->next
199        = reinterpret_cast<Link*>(storePtr + i + 1);
200    }
201    reinterpret_cast<Link*>(storePtr + i)->next = 0;
202  }
203
204};
205#endif /* 0 */
206
207#endif /* ADOL_C__STOREMANAGER_H */
208
Note: See TracBrowser for help on using the repository browser.