Cyclops Tensor Framework
parallel arithmetic on multidimensional arrays
idx_tensor.cxx
Go to the documentation of this file.
1 /*Copyright (c) 2013, Edgar Solomonik, all rights reserved.*/
2 
3 #include "common.h"
4 #include "schedule.h"
5 #include "../summation/summation.h"
6 
7 using namespace CTF_int;
8 
9 namespace CTF {
10 
11  //template<typename dtype, bool is_ord>
12  //Idx_Tensor get_intermediate(Idx_Tensor& A,
13  // Idx_Tensor& B){
14  // int * len_C, * sym_C;
15  // char * idx_C;
16  // int order_C, i, j, idx;
17  //
18  // order_C = 0;
19  // for (i=0; i<A.parent->order; i++){
20  // order_C++;
21  // for (j=0; j<B.parent->order; j++){
22  // if (A.idx_map[i] == B.idx_map[j]){
23  // order_C--;
24  // break;
25  // }
26  // }
27  // }
28  // for (j=0; j<B.parent->order; j++){
29  // order_C++;
30  // for (i=0; i<A.parent->order; i++){
31  // if (A.idx_map[i] == B.idx_map[j]){
32  // order_C--;
33  // break;
34  // }
35  // }
36  // }
37  //
38  // idx_C = (char*)CTF_int::alloc(sizeof(char)*order_C);
39  // sym_C = (int*)CTF_int::alloc(sizeof(int)*order_C);
40  // len_C = (int*)CTF_int::alloc(sizeof(int)*order_C);
41  // idx = 0;
42  // for (i=0; i<A.parent->order; i++){
43  // for (j=0; j<B.parent->order; j++){
44  // if (A.idx_map[i] == B.idx_map[j]){
45  // break;
46  // }
47  // }
48  // if (j == B.parent->order){
49  // idx_C[idx] = A.idx_map[i];
50  // len_C[idx] = A.parent->len[i];
51  // if (idx >= 1 && i >= 1 && idx_C[idx-1] == A.idx_map[i-1] && A.parent->sym[i-1] != NS){
52  // sym_C[idx-1] = A.parent->sym[i-1];
53  // }
54  // sym_C[idx] = NS;
55  // idx++;
56  // }
57  // }
58  // for (j=0; j<B.parent->order; j++){
59  // for (i=0; i<A.parent->order; i++){
60  // if (A.idx_map[i] == B.idx_map[j]){
61  // break;
62  // }
63  // }
64  // if (i == A.parent->order){
65  // idx_C[idx] = B.idx_map[j];
66  // len_C[idx] = B.parent->len[j];
67  // if (idx >= 1 && j >= 1 && idx_C[idx-1] == B.idx_map[j-1] && B.parent->sym[j-1] != NS){
68  // sym_C[idx-1] = B.parent->sym[j-1];
69  // }
70  // sym_C[idx] = NS;
71  // idx++;
72  // }
73  // }
74  //
75  // CTF_int::tensor * tsr_C = new CTF_int::tensor(order_C, len_C, sym_C, *(A.parent->world));
76  // Idx_Tensor out(tsr_C, idx_C);
77  // out.is_intm = 1;
78  // free(sym_C);
79  // free(len_C);
80  // return out;
81  //}
82 
84  const char * idx_map_,
85  int copy) : Term(parent_->sr) {
86  idx_map = (char*)CTF_int::alloc(parent_->order*sizeof(char));
87  if (copy){
88  parent = new CTF_int::tensor(parent,1);
89  } else {
90  parent = parent_;
91  }
92  memcpy(idx_map, idx_map_, parent->order*sizeof(char));
93  is_intm = 0;
94  }
95 
97  idx_map = NULL;
98  parent = NULL;
99  is_intm = 0;
100  }
101 
102  Idx_Tensor::Idx_Tensor(algstrct const * sr, double scl) : Term(sr) {
103  idx_map = NULL;
104  parent = NULL;
105  is_intm = 0;
106  sr->cast_double(scl, scale);
107  }
108 
109  Idx_Tensor::Idx_Tensor(algstrct const * sr, int64_t scl) : Term(sr) {
110  idx_map = NULL;
111  parent = NULL;
112  is_intm = 0;
113  sr->cast_int(scl, scale);
114  }
115 
117  int copy,
118  std::map<tensor*, tensor*>* remap) : Term(other.sr) {
119  if (other.parent == NULL){
120  parent = NULL;
121  idx_map = NULL;
122  is_intm = 0;
123  } else {
124  parent = other.parent;
125  if (remap != NULL) {
126  typename std::map<CTF_int::tensor*, CTF_int::tensor*>::iterator it = remap->find(parent);
127  assert(it != remap->end()); // assume a remapping will be complete
128  parent = it->second;
129  }
130 
131  if (copy || other.is_intm){
132  parent = new CTF_int::tensor(other.parent,1);
133  is_intm = 1;
134  } else {
135  // leave parent as is - already correct
136  is_intm = 0;
137  }
138  idx_map = (char*)CTF_int::alloc(other.parent->order*sizeof(char));
139  memcpy(idx_map, other.idx_map, parent->order*sizeof(char));
140  }
141  sr->safecopy(scale,other.scale);
142  }
143 
144 /* Idx_Tensor::Idx_Tensor(){
145  parent = NULL;
146  idx_map = NULL;
147  is_intm = 0;
148  sr->copy(scale,sr->mulid());
149  }
150 
151  Idx_Tensor::Idx_Tensor(double val) : Term(NULL) {
152  parent = NULL;
153  idx_map = NULL;
154  is_intm = 0;
155  scale = (char*)alloc(sizeof(double));
156  sr->copy(scale,(char const*)&val);
157  }*/
158 
160  if (is_intm) {
161  delete parent;
162  is_intm = 0;
163  }
164  if (parent != NULL) cdealloc(idx_map);
165  idx_map = NULL;
166  }
167 
168  Term * Idx_Tensor::clone(std::map<CTF_int::tensor*, CTF_int::tensor*>* remap) const {
169  return new Idx_Tensor(*this, 0, remap);
170  }
171 
173  if (parent == NULL) return NULL;
174  return parent->wrld;
175  }
176 
178  if (global_schedule != NULL) {
179  std::cout << "op= tensor" << std::endl;
180  assert(false);
181  } else {
182  if (sr->has_mul()){
183  sr->safecopy(scale,sr->addid());
184  } else {
185  this->parent->set_zero();
186  }
187  B.execute(*this);
188  sr->safecopy(scale,sr->mulid());
189  }
190  }
191 
192  void Idx_Tensor::operator=(Term const & B){
193  if (global_schedule != NULL) {
195  new TensorOperation(TENSOR_OP_SET, new Idx_Tensor(*this), B.clone()));
196  } else {
197  if (sr->has_mul()){
198  sr->safecopy(scale,sr->addid());
199  } else {
200  this->parent->set_zero();
201  }
202  B.execute(*this);
203  sr->safecopy(scale,sr->mulid());
204  }
205  }
206 
207  void Idx_Tensor::operator+=(Term const & B){
208  if (global_schedule != NULL) {
210  new TensorOperation(TENSOR_OP_SUM, new Idx_Tensor(*this), B.clone()));
211  } else {
212  //sr->copy(scale,sr->mulid());
213  B.execute(*this);
214  sr->safecopy(scale,sr->mulid());
215  }
216  }
217 
218  void Idx_Tensor::operator=(double scl){ this->execute(this->get_uniq_inds()) = Idx_Tensor(sr,scl); }
219  void Idx_Tensor::operator+=(double scl){ this->execute(this->get_uniq_inds()) += Idx_Tensor(sr,scl); }
220  void Idx_Tensor::operator-=(double scl){ this->execute(this->get_uniq_inds()) -= Idx_Tensor(sr,scl); }
221  void Idx_Tensor::operator*=(double scl){ this->execute(this->get_uniq_inds()) *= Idx_Tensor(sr,scl); }
222  void Idx_Tensor::multeq(double scl){ this->execute(this->get_uniq_inds()) *= Idx_Tensor(sr,scl); }
223 
224  void Idx_Tensor::operator=(int64_t scl){ this->execute(this->get_uniq_inds()) = Idx_Tensor(sr,scl); }
225  void Idx_Tensor::operator+=(int64_t scl){ this->execute(this->get_uniq_inds()) += Idx_Tensor(sr,scl); }
226  void Idx_Tensor::operator-=(int64_t scl){ this->execute(this->get_uniq_inds()) -= Idx_Tensor(sr,scl); }
227  void Idx_Tensor::operator*=(int64_t scl){ this->execute(this->get_uniq_inds()) *= Idx_Tensor(sr,scl); }
228 
229  void Idx_Tensor::operator=(int scl){ this->execute(this->get_uniq_inds()) = Idx_Tensor(sr,(int64_t)scl); }
230  void Idx_Tensor::operator+=(int scl){ this->execute(this->get_uniq_inds()) += Idx_Tensor(sr,(int64_t)scl); }
231  void Idx_Tensor::operator-=(int scl){ this->execute(this->get_uniq_inds()) -= Idx_Tensor(sr,(int64_t)scl); }
232  void Idx_Tensor::operator*=(int scl){ this->execute(this->get_uniq_inds()) *= Idx_Tensor(sr,(int64_t)scl); }
233 
234  /*Idx_Tensor Idx_Tensor::operator-() const {
235 
236  Idx_Tensor trm(*this);
237  sr->safeaddinv(trm.scale,trm.scale);
238  return trm;
239  }*/
240 
241  void Idx_Tensor::operator-=(Term const & B){
242  if (global_schedule != NULL) {
244  new TensorOperation(TENSOR_OP_SUBTRACT, new Idx_Tensor(*this), B.clone()));
245  } else {
246  Term * Bcpy = B.clone();
247  char * ainv = NULL;
248  B.sr->safeaddinv(B.sr->mulid(),ainv);
249  B.sr->safemul(Bcpy->scale,ainv,Bcpy->scale);
250  Bcpy->execute(*this);
251  sr->safecopy(scale,sr->mulid());
252  if (ainv != NULL) cdealloc(ainv);
253  delete Bcpy;
254  }
255  }
256 
257  void Idx_Tensor::operator*=(Term const & B){
258  if (global_schedule != NULL) {
260  new TensorOperation(TENSOR_OP_MULTIPLY, new Idx_Tensor(*this), B.clone()));
261  } else {
262  Contract_Term ctrm = (*this)*B;
263  *this = ctrm;
264  }
265  }
266 
267 
268 
269 
270  void Idx_Tensor::execute(Idx_Tensor output) const {
271  if (parent == NULL){
272 // output.sr->safemul(output.scale, scale, output.scale);
273  CTF_int::tensor ts(output.sr, 0, NULL, NULL, output.where_am_i(), true, NULL, 0);
274  char * data;
275  int64_t sz;
276  ts.get_raw_data(&data, &sz);
277  if (ts.wrld->rank == 0) ts.sr->safecopy(data, scale);
278  summation s(&ts, NULL, ts.sr->mulid(),
279  output.parent, output.idx_map, output.scale);
280  s.execute();
281  } else {
282  summation s(this->parent, idx_map, scale,
283  output.parent, output.idx_map, output.scale);
284  s.execute();
285 // output.parent->sum(scale, *this->parent, idx_map,
286  // output.scale, output.idx_map);
287  }
288  }
289 
290  Idx_Tensor Idx_Tensor::execute(std::vector<char> out_inds) const {
291  return *this;
292  }
293 
294  double Idx_Tensor::estimate_time(Idx_Tensor output) const {
295  if (parent == NULL){
296  CTF_int::tensor ts(output.sr, 0, NULL, NULL, output.where_am_i(), true, NULL, 0);
297  summation s(&ts, NULL, output.sr->mulid(),
298  output.parent, output.idx_map, output.scale);
299  return s.estimate_time();
300  } else {
301  summation s(this->parent, idx_map, scale,
302  output.parent, output.idx_map, output.scale);
303  return s.estimate_time();
304  }
305  }
306 
307  Idx_Tensor Idx_Tensor::estimate_time(double & cost, std::vector<char> out_inds) const {
308  return *this;
309  }
310 
311  std::vector<char> Idx_Tensor::get_uniq_inds() const {
312  if (parent == NULL) return std::vector<char>();
313  std::set<char> uniq_inds;
314  for (int k=0; k<this->parent->order; k++){
315  uniq_inds.insert(idx_map[k]);
316  }
317  return std::vector<char>(uniq_inds.begin(), uniq_inds.end());
318  }
319 
320  void Idx_Tensor::get_inputs(std::set<Idx_Tensor*, tensor_name_less >* inputs_set) const {
321  inputs_set->insert((Idx_Tensor*)this);
322  }
323 
324  /*template<typename dtype, bool is_ord>
325  void Idx_Tensor::operator=(dtype B){
326  *this=(Scalar(B,*(this->parent->world))[""]);
327  }
328  void Idx_Tensor::operator+=(dtype B){
329  *this+=(Scalar(B,*(this->parent->world))[""]);
330  }
331  void Idx_Tensor::operator-=(dtype B){
332  *this-=(Scalar(B,*(this->parent->world))[""]);
333  }
334  void Idx_Tensor::operator*=(dtype B){
335  *this*=(Scalar(B,*(this->parent->world))[""]);
336  }*/
337 
338  /*
339  Idx_Tensor Idx_Tensor::operator+(Idx_Tensor tsr){
340  if (has_contract || has_sum){
341  *NBR = (*NBR)-tsr;
342  return *this;
343  }
344  NBR = &tsr;
345  has_sum = 1;
346  return *this;
347  }
348 
349  Idx_Tensor Idx_Tensor::operator-(Idx_Tensor tsr){
350  if (has_contract || has_sum){
351  *NBR = (*NBR)-tsr;
352  return *this;
353  }
354  NBR = &tsr;
355  has_sum = 1;
356  if (tsr.has_scale) tsr.scale = -sr->mulid*tsr.scale;
357  else {
358  tsr.has_scale = 1;
359  tsr.scale = -sr->mulid();
360  }
361  return *this;
362  }
363 
364  Idx_Tensor Idx_Tensor::operator*(double scl){
365  if (has_contract){
366  *NBR =(*NBR)*scl;
367  return *this;
368  }
369  if (has_scale){
370  scale *= scl;
371  } else {
372  has_scale = 1;
373  scale = scl;
374  }
375  return *this;
376  }*/
377 
378  /*
379  void Idx_Tensor::run(Idx_Tensor* output, dtype beta){
380  dtype alpha;
381  if (has_scale) alpha = scale;
382  else alpha = sr->mulid();
383  if (has_contract){
384  if (NBR->has_scale){
385  alpha *= NBR->scale;
386  }
387  if (NBR->has_contract || NBR->has_sum){
388  Idx_Tensor itsr = get_intermediate(*this,*NBR);
389  itsr.has_sum = NBR->has_sum;
390  itsr.has_contract = NBR->has_contract;
391  itsr.NBR = NBR->NBR;
392  printf("erm tsr has_Contract = %d, NBR = %p, NBR.has_scale = %d\n", itsr.has_contract, itsr.NBR,
393  itsr.NBR->has_scale);
394 
395  itsr.parent->contract(alpha, *(this->parent), this->idx_map,
396  *(NBR->parent), NBR->idx_map,
397  sr->addid(), itsr.idx_map);
398  itsr.run(output, beta);
399  } else {
400  output->parent->contract(alpha, *(this->parent), this->idx_map,
401  *(NBR->parent), NBR->idx_map,
402  beta, output->idx_map);
403  }
404  } else {
405  if (has_sum){
406  CTF_int::tensor tcpy(*(this->parent),1);
407  Idx_Tensor itsr(&tcpy, idx_map);
408  NBR->run(&itsr, alpha);
409  output->parent->sum(sr->mulid, tcpy, idx_map, beta, output->idx_map);
410  // delete itsr;
411  // delete tcpy;
412  } else {
413  output->parent->sum(alpha, *(this->parent), idx_map, beta, output->idx_map);
414  }
415  }
416  // if (!is_perm)
417  // delete this;
418  }*/
419 
420 }
void get_raw_data(char **data, int64_t *size) const
get raw data pointer without copy WARNING: includes padding
a term is an abstract object representing some expression of tensors
Definition: term.h:33
algstrct * sr
Definition: term.h:36
void operator+=(double scl)
Definition: idx_tensor.cxx:219
virtual void execute(CTF::Idx_Tensor output) const =0
evalues the expression, which just scales by default
void safecopy(char *&a, char const *b) const
copies element b to element a, , with checks for NULL and alloc as necessary
Definition: algstrct.cxx:529
void execute(bool run_diag=false)
run summation
Definition: summation.cxx:119
char * idx_map
Definition: idx_tensor.h:18
void * alloc(int64_t len)
alloc abstraction
Definition: memcontrol.cxx:365
virtual char const * addid() const
MPI datatype for pairs.
Definition: algstrct.cxx:89
void get_inputs(std::set< Idx_Tensor *, CTF_int::tensor_name_less > *inputs_set) const
appends the tensors this depends on to the input set
Definition: idx_tensor.cxx:320
A tensor operation, containing all the data (op, lhs, rhs) required to run it. Also provides methods ...
Definition: schedule.h:34
an instance of the CTF library (world) on a MPI communicator
Definition: world.h:19
virtual void safemul(char const *a, char const *b, char *&c) const
c = a*b, with NULL treated as mulid
Definition: algstrct.cxx:126
int order
number of tensor dimensions
double estimate_time()
predicts execution time in seconds using performance models
Definition: summation.cxx:132
CTF::World * wrld
distributed processor context on which tensor is defined
virtual bool has_mul() const
Definition: algstrct.h:109
virtual Term * clone(std::map< tensor *, tensor * > *remap=NULL) const =0
base classes must implement this copy function to retrieve pointer
CTF_int::Term * clone(std::map< CTF_int::tensor *, CTF_int::tensor * > *remap=NULL) const
base classes must implement this copy function to retrieve pointer
Definition: idx_tensor.cxx:168
virtual void cast_int(int64_t i, char *c) const
c = &i
Definition: algstrct.cxx:144
Idx_Tensor(CTF_int::tensor *parent_, const char *idx_map_, int copy=0)
constructor takes in a parent tensor and its indices
Definition: idx_tensor.cxx:83
int set_zero()
elects a mapping and sets tensor data to zero
def copy(tensor, A)
Definition: core.pyx:3583
double estimate_time(Idx_Tensor output) const
estimates the cost of a contraction
Definition: idx_tensor.cxx:294
std::vector< char > get_uniq_inds() const
find list of unique indices that are involved in this term
Definition: idx_tensor.cxx:311
int cdealloc(void *ptr)
free abstraction
Definition: memcontrol.cxx:480
Idx_Tensor execute(std::vector< char > out_inds) const
evalues the expression to produce an intermediate with all expression indices remaining ...
Definition: idx_tensor.cxx:290
algstrct (algebraic structure) defines the elementwise operations computed in each tensor contraction...
Definition: algstrct.h:34
Definition: apsp.cxx:17
internal distributed tensor class
ScheduleBase * global_schedule
Definition: schedule.cxx:8
void operator=(CTF_int::Term const &B)
A = B, compute any operations on operand B and set.
Definition: idx_tensor.cxx:192
char * scale
Definition: term.h:35
virtual void add_operation(TensorOperationBase *op)=0
void operator-=(double scl)
Definition: idx_tensor.cxx:220
class for execution distributed summation of tensors
Definition: summation.h:15
An experession representing a contraction of a set of tensors contained in operands.
Definition: term.h:275
virtual void cast_double(double d, char *c) const
c = &d
Definition: algstrct.cxx:150
virtual void safeaddinv(char const *a, char *&b) const
b = -a, with checks for NULL and alloc as necessary
Definition: algstrct.cxx:97
virtual char const * mulid() const
identity element for multiplication i.e. 1
Definition: algstrct.cxx:93
a tensor with an index map associated with it (necessary for overloaded operators) ...
Definition: idx_tensor.h:15
World * where_am_i() const
figures out what world this term lives on
Definition: idx_tensor.cxx:172
void operator*=(double scl)
Definition: idx_tensor.cxx:221
void multeq(double scl)
Definition: idx_tensor.cxx:222
CTF_int::tensor * parent
Definition: idx_tensor.h:17