MyraMath
Workspace.h
Go to the documentation of this file.
1 // ========================================================================= //
2 // This file is part of MyraMath, copyright (c) 2014-2019 by Ryan A Chilton //
3 // and distributed by MyraCore, LLC. See LICENSE.txt for license terms. //
4 // ========================================================================= //
5 
6 #ifndef MYRAMATH_UTILITY_WORKSPACE_H
7 #define MYRAMATH_UTILITY_WORKSPACE_H
8 
14 // Serialization interface.
15 #include <myramath/io/Streams.h>
17 
18 // Initialize with diabolical values? (just for testing)
20 
21 #include <cstdlib>
22 #include <iostream>
23 
24 namespace myra {
25 
26 // Implementation detail of member swap. Why not use std::swap? Trying to avoid dependence on #include<algorithm>
27 template<class POD> void swap_pod(POD& pod1, POD& pod2)
28  {
29  POD temp = pod1;
30  pod1 = pod2;
31  pod2 = temp;
32  }
33 
35 template<class T> class Workspace
36  {
37  public:
38 
40  Workspace() : p(0), S(0)
41  { }
42 
44  explicit Workspace(size_t in_S) : p(0), S(0)
45  { allocate(in_S); }
46 
48  Workspace(const Workspace& that) : p(0), S(0)
49  {
50  allocate(that.S);
51  for (size_t s = 0; s < S; ++s)
52  (*this)[s] = that[s];
53  }
54 
56  void swap(Workspace& that)
57  {
58  swap_pod(this->S, that.S);
59  swap_pod(this->p, that.p);
60  }
61 
64  { this->swap(that); return *this; }
65 
67  explicit Workspace(InputStream& in) : p(0), S(0)
68  {
69  allocate(in.read<size_t>());
70  for (size_t s = 0; s < S; ++s)
71  in >> p[s];
72  }
73 
75  void write(OutputStream& out) const
76  {
77  out << S;
78  for (size_t s = 0; s < S; ++s)
79  out << p[s];
80  }
81 
83  const T& operator () (size_t i) const { return p[i]; }
84  T& operator () (size_t i) { return p[i]; }
85 
87  const T& operator [] (size_t i) const { return p[i]; }
88  T& operator [] (size_t i) { return p[i]; }
89 
91  T* begin() { return p; }
92  T* end() { return p+S; }
93 
95  const T* begin() const { return p; }
96  const T* end() const { return p+S; }
97 
99  size_t size() const
100  { return S; }
101 
103  void resize(size_t R)
104  {
105  deallocate();
106  allocate(R);
107  }
108 
110  void resize(size_t R, T t)
111  {
112  resize(R);
113  for (size_t s = 0; s < S; ++s)
114  (*this)[s] = t;
115  }
116 
118  void touch()
119  {
120  for (size_t s = 0; s < S; s += 1024)
121  (*this)[s] = 0;
122  }
123 
126  { deallocate(); }
127 
128  private:
129 
130  // Allocates with size S
131  void allocate(size_t in_S)
132  {
133  S = in_S;
134  p = 0;
135  if (S)
136  {
137  p = (T*)malloc(sizeof(T)*S);
138  if (!p)
139  throw std::bad_alloc();
140  }
141 
142  // To test/verify that clients don't rely on workspace
143  // being initialized, can populate p[] with junk data..
144  // for (int s = 0; s < S; ++s) p[s] = random<T>();
145 
146  // ..however some BLAS/LAPACK implementations may actually
147  // require workspace to be initialized with valid numbers
148  // before first touch ***, so consider zeroing it.
149  // for (int s = 0; s < S; ++s) p[s] = T(0);
150  }
151 
152  // *** Note ***
153  //
154  // This remark is more subtle than it first appears. An unitialized
155  // workspace might have any random bit pattern in it. When updating
156  // a workspace that is known to be uninitialized, the first touch will
157  // always be a careful BLAS write (like gemm, syrk, or herk) with
158  // alpha != 0 and beta = 0. However, if there is a Number c within an
159  // unitialized workspace that unluckily has (for instance) some sort
160  // of NaN bit pattern, it cannot actually be cleared by an operation
161  // of the form c = alpha*a*b + beta*c! The pre-existing NaN persists,
162  // despite the fact that we tried to "clear" it by using beta=0.
163  //
164  // Some BLAS's can tolerate input NaN's, some cannot. For instance,
165  // MKL explicitly guarantees "when beta is equal to zero, then c
166  // need not be set on input" in the documentation for gemm(). MyraKL
167  // is also tolerant of input NaN's. The reference BLAS is not.
168  //
169  // In fact, there are many bit patterns that all can represent a NaN,
170  // so it's not at all unusual to encounter one in unitialized memory
171  // carved from the heap.
172 
173  // Deallocates.
174  void deallocate()
175  {
176  free(p);
177  p = 0;
178  }
179 
180  // Pointer to internal contents.
181  T* p;
182 
183  // Total size.
184  size_t S;
185 
186  };
187 
189 template<class T> std::ostream& operator << (std::ostream& out, const Workspace<T>& w)
190  {
191  out << "[ ";
192  for (const T* i = w.begin(); i != w.end(); ++i)
193  out << *i << " ";
194  out << "] (" << w.size() << ")";
195  return out;
196  }
197 
198 } // namespace myra
199 
200 #endif
void touch()
Explicit first-touch.
Definition: Workspace.h:118
void write(OutputStream &out) const
Writes to OutputStream.
Definition: Workspace.h:75
ReaderWriter<T>, encapsulates a read()/write() pair for type T.
size_t size() const
Size inspector.
Definition: Workspace.h:99
Workspace(InputStream &in)
InputStream constructor.
Definition: Workspace.h:67
Definition: syntax.dox:1
Workspace(const Workspace &that)
Copy constructor. Does initialize values (by copying from that)
Definition: Workspace.h:48
Abstraction layer, serializable objects write themselves to these.
Definition: Streams.h:39
T * begin()
Mutable pointer range over contiguous storage.
Definition: Workspace.h:91
void swap(Workspace &that)
Member swap.
Definition: Workspace.h:56
const T & operator[](size_t i) const
Random accessor/mutator, operator [].
Definition: Workspace.h:87
Abstraction layer, deserializable objects read themselves from these.
Definition: Streams.h:47
void resize(size_t R)
Resizes, does not initialize with values.
Definition: Workspace.h:103
Fixed size container of values.
Definition: Workspace.h:35
Workspace()
Default constructor, makes size 0.
Definition: Workspace.h:40
void resize(size_t R, T t)
Resizes, does initialize with values.
Definition: Workspace.h:110
const T & operator()(size_t i) const
Random accessor/mutator, operator ()
Definition: Workspace.h:83
~Workspace()
Frees internal resources.
Definition: Workspace.h:125
Workspace & operator=(Workspace that)
Copy-assignment operator, copy construct and swap idiom.
Definition: Workspace.h:63
const T * begin() const
Const pointer range over contiguous storage.
Definition: Workspace.h:95
Simplistic random number functions.
Workspace(size_t in_S)
Constructor, requires size. Does not initialize values.
Definition: Workspace.h:44
Bases classes for binary input/output streams.