00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef __GNUC__
00029 #pragma interface
00030 #endif
00031
00032 #ifndef _util_group_memory_h
00033 #define _util_group_memory_h
00034
00035 #include <iostream>
00036
00037 #include <scconfig.h>
00038 #include <util/class/class.h>
00039 #include <util/group/thread.h>
00040
00041 namespace sc {
00042
00043 #if 0 // this can be used to catch accidental conversions to int
00044 class distsize_t {
00045 friend size_t distsize_to_size(const distsize_t &a);
00046 friend distsize_t operator *(const int &a,const distsize_t &b);
00047 friend distsize_t operator +(const int &a,const distsize_t &b);
00048 friend distsize_t operator -(const int &a,const distsize_t &b);
00049 friend distsize_t operator /(const int &a,const distsize_t &b);
00050 friend distsize_t operator %(const int &a,const distsize_t &b);
00051 friend ostream& operator <<(ostream& o, const distsize_t &s);
00052 private:
00053 unsigned long long s;
00054 public:
00055 distsize_t(): s(999999999999999LL) {}
00056 distsize_t(int a): s(a) {}
00057 distsize_t(unsigned int a): s(a) {}
00058 distsize_t(unsigned long long a): s(a) {}
00059 distsize_t &operator =(const distsize_t &a)
00060 { s=a.s; return *this; }
00061 distsize_t &operator +=(const distsize_t &a)
00062 { s+=a.s; return *this; }
00063 distsize_t operator *(const distsize_t &a) const
00064 { return s*a.s; }
00065 distsize_t operator +(const distsize_t &a) const
00066 { return s+a.s; }
00067 distsize_t operator -(const distsize_t &a) const
00068 { return s-a.s; }
00069 distsize_t operator /(const distsize_t &a) const
00070 { return s/a.s; }
00071 distsize_t operator %(const distsize_t &a) const
00072 { return s%a.s; }
00073 bool operator <(const distsize_t &a) const
00074 { return s<a.s; }
00075 bool operator <=(const distsize_t &a) const
00076 { return s<=a.s; }
00077 bool operator >(const distsize_t &a) const
00078 { return s>a.s; }
00079 bool operator >=(const distsize_t &a) const
00080 { return s>=a.s; }
00081 bool operator ==(const distsize_t &a) const
00082 { return s==a.s; }
00083 distsize_t operator *(const int &a) const
00084 { return s*a; }
00085 distsize_t operator +(const int &a) const
00086 { return s+a; }
00087 distsize_t operator -(const int &a) const
00088 { return s-a; }
00089 distsize_t operator /(const int &a) const
00090 { return s/a; }
00091 distsize_t operator %(const int &a) const
00092 { return s%a; }
00093 };
00094 inline distsize_t operator *(const int &a,const distsize_t &b)
00095 { return a*b.s; }
00096 inline distsize_t operator +(const int &a,const distsize_t &b)
00097 { return a+b.s; }
00098 inline distsize_t operator -(const int &a,const distsize_t &b)
00099 { return a-b.s; }
00100 inline distsize_t operator /(const int &a,const distsize_t &b)
00101 { return a/b.s; }
00102 inline distsize_t operator %(const int &a,const distsize_t &b)
00103 { return a%b.s; }
00104 inline ostream& operator <<(ostream& o, const distsize_t &s) { return o<<s.s; }
00105 inline size_t distsize_to_size(const distsize_t &a) {return a.s;}
00106 #elif defined(HAVE_LONG_LONG)
00107 typedef unsigned long long distsize_t;
00108 typedef long long distssize_t;
00109 inline size_t distsize_to_size(const distsize_t &a) {return a;}
00110 #else
00111 typedef unsigned long distsize_t;
00112 typedef long distssize_t;
00113 inline size_t distsize_to_size(const distsize_t &a) {return a;}
00114 #endif
00115
00124 class MemoryGrp: public DescribedClass {
00125 private:
00126 Ref<ThreadLock> *locks_;
00127 int nlock_;
00128
00129 void init_locks();
00130
00131
00132 protected:
00133
00134
00135 int me_;
00136 int n_;
00137 distsize_t *offsets_;
00138
00139
00140 int debug_;
00141
00142 void obtain_local_lock(size_t start, size_t fence);
00143 void release_local_lock(size_t start, size_t fence);
00144 public:
00145 MemoryGrp();
00146 MemoryGrp(const Ref<KeyVal>&);
00147 virtual ~MemoryGrp();
00148
00150 int me() const { return me_; }
00152 int n() const { return n_; }
00153
00157 virtual void set_localsize(size_t) = 0;
00159 size_t localsize() { return distsize_to_size(offsets_[me_+1]-offsets_[me_]); }
00161 virtual void *localdata() = 0;
00163 distsize_t localoffset() { return offsets_[me_]; }
00165 int size(int node)
00166 { return distsize_to_size(offsets_[node+1] - offsets_[node]); }
00168 distsize_t offset(int node) { return offsets_[node]; }
00170 distsize_t totalsize() { return offsets_[n_]; }
00171
00173 virtual void activate();
00175 virtual void deactivate();
00176
00178 virtual void *obtain_writeonly(distsize_t offset, int size) = 0;
00184 virtual void *obtain_readwrite(distsize_t offset, int size) = 0;
00186 virtual void *obtain_readonly(distsize_t offset, int size) = 0;
00188 virtual void release_readonly(void *data, distsize_t offset, int size) = 0;
00190 virtual void release_writeonly(void *data, distsize_t offset, int size)=0;
00193 virtual void release_readwrite(void *data, distsize_t offset, int size)=0;
00194
00195 virtual void sum_reduction(double *data, distsize_t doffset, int dsize);
00196 virtual void sum_reduction_on_node(double *data, size_t doffset, int dsize,
00197 int node = -1);
00198
00202 virtual void sync() = 0;
00203
00208 virtual void* malloc_local(size_t nbyte);
00209 virtual double* malloc_local_double(size_t ndouble);
00210
00212 virtual void free_local(void *data);
00213 virtual void free_local_double(double *data);
00214
00221 virtual void catchup();
00222
00226 virtual Ref<MemoryGrp> clone(void);
00227
00229 virtual void print(std::ostream &o = ExEnv::out0()) const;
00230
00238 static MemoryGrp* initial_memorygrp(int &argc, char** argv);
00239 static MemoryGrp* initial_memorygrp();
00242 static void set_default_memorygrp(const Ref<MemoryGrp>&);
00248 static MemoryGrp* get_default_memorygrp();
00249 };
00250
00251
00257 template <class data_t>
00258 class MemoryGrpBuf {
00259 Ref<MemoryGrp> grp_;
00260 enum AccessType { None, Read, Write, ReadWrite };
00261 AccessType accesstype_;
00262 data_t *data_;
00263 distsize_t offset_;
00264 int length_;
00265 public:
00269 MemoryGrpBuf(const Ref<MemoryGrp> &);
00274 data_t *writeonly(distsize_t offset, int length);
00279 data_t *readwrite(distsize_t offset, int length);
00284 const data_t *readonly(distsize_t offset, int length);
00288 data_t *writeonly_on_node(size_t offset, int length, int node = -1);
00289 data_t *readwrite_on_node(size_t offset, int length, int node = -1);
00290 const data_t *readonly_on_node(size_t offset, int length, int node = -1);
00294 void release();
00296 int length() const { return length_; }
00297 };
00298
00300
00301
00302 template <class data_t>
00303 MemoryGrpBuf<data_t>::MemoryGrpBuf(const Ref<MemoryGrp> & grp)
00304 {
00305 grp_ = grp;
00306 accesstype_ = None;
00307 }
00308
00309 template <class data_t>
00310 data_t *
00311 MemoryGrpBuf<data_t>::writeonly(distsize_t offset, int length)
00312 {
00313 if (accesstype_ != None) release();
00314 data_ = (data_t *) grp_->obtain_writeonly(sizeof(data_t)*offset,
00315 sizeof(data_t)*length);
00316 offset_ = offset;
00317 length_ = length;
00318 accesstype_ = Write;
00319 return data_;
00320 }
00321
00322 template <class data_t>
00323 data_t *
00324 MemoryGrpBuf<data_t>::readwrite(distsize_t offset, int length)
00325 {
00326 if (accesstype_ != None) release();
00327 data_ = (data_t *) grp_->obtain_readwrite(sizeof(data_t)*offset,
00328 sizeof(data_t)*length);
00329 offset_ = offset;
00330 length_ = length;
00331 accesstype_ = ReadWrite;
00332 return data_;
00333 }
00334
00335 template <class data_t>
00336 const data_t *
00337 MemoryGrpBuf<data_t>::readonly(distsize_t offset, int length)
00338 {
00339 if (accesstype_ != None) release();
00340 data_ = (data_t *) grp_->obtain_readonly(sizeof(data_t)*offset,
00341 sizeof(data_t)*length);
00342 offset_ = offset;
00343 length_ = length;
00344 accesstype_ = Read;
00345 return data_;
00346 }
00347
00348 template <class data_t>
00349 data_t *
00350 MemoryGrpBuf<data_t>::writeonly_on_node(size_t offset, int length, int node)
00351 {
00352 if (node == -1) node = grp_->me();
00353 return writeonly(offset + grp_->offset(node)/sizeof(data_t), length);
00354 }
00355
00356 template <class data_t>
00357 data_t *
00358 MemoryGrpBuf<data_t>::readwrite_on_node(size_t offset, int length, int node)
00359 {
00360 if (node == -1) node = grp_->me();
00361 return readwrite(offset + grp_->offset(node)/sizeof(data_t), length);
00362 }
00363
00364 template <class data_t>
00365 const data_t *
00366 MemoryGrpBuf<data_t>::readonly_on_node(size_t offset, int length, int node)
00367 {
00368 if (node == -1) node = grp_->me();
00369 return readonly(offset + grp_->offset(node)/sizeof(data_t), length);
00370 }
00371
00372 template <class data_t>
00373 void
00374 MemoryGrpBuf<data_t>::release()
00375 {
00376 if (accesstype_ == Write)
00377 grp_->release_writeonly((data_t *)data_,
00378 sizeof(data_t)*offset_, sizeof(data_t)*length_);
00379 if (accesstype_ == Read)
00380 grp_->release_readonly(data_, sizeof(data_t)*offset_,
00381 sizeof(data_t)*length_);
00382 if (accesstype_ == ReadWrite)
00383 grp_->release_readwrite(data_, sizeof(data_t)*offset_,
00384 sizeof(data_t)*length_);
00385
00386 accesstype_ = None;
00387 }
00388
00389 }
00390
00391 #endif
00392
00393
00394
00395
00396