Cyclops Tensor Framework
parallel arithmetic on multidimensional arrays
bivar_transform.cxx
Go to the documentation of this file.
1 /*Copyright (c) 2011, Edgar Solomonik, all rights reserved.*/
2 
10 #include <ctf.hpp>
11 using namespace CTF;
12 
13 void f3(double a, double b, double & c){
14  c = a*c*a+b*c*b;
15 }
16 
17 int bivar_transform(int n,
18  World & dw){
19 
20  int shapeN4[] = {NS,NS,NS,NS};
21  int sizeN4[] = {n+1,n,n+2,n+3};
22 
23  Tensor<> A(4, sizeN4, shapeN4, dw);
24  Tensor<> B(4, sizeN4, shapeN4, dw);
25  Tensor<> C(4, sizeN4, shapeN4, dw);
26 
27  srand48(dw.rank);
28  A.fill_random(-.5, .5);
29  B.fill_random(-.5, .5);
30  C.fill_random(-.5, .5);
31 
32 
33  double * all_start_data_A;
34  int64_t nall_A;
35  A.read_all(&nall_A, &all_start_data_A);
36  double * all_start_data_B;
37  int64_t nall_B;
38  B.read_all(&nall_B, &all_start_data_B);
39  double * all_start_data_C;
40  int64_t nall_C;
41  C.read_all(&nall_C, &all_start_data_C);
42 
43  CTF::Transform<> bfun([](double a, double b, double & c){ c = a*c*a + b*c*b; });
44  bfun(A["ijkl"],B["ijkl"],C["ijkl"]);
45 
46  double * all_end_data_C;
47  int64_t nall2_C;
48  C.read_all(&nall2_C, &all_end_data_C);
49 
50  int pass = (nall_C == nall2_C);
51  if (pass){
52  for (int64_t i=0; i<nall_A; i++){
53  double k = all_start_data_C[i];
54  f3(all_start_data_A[i],all_start_data_B[i], k);
55  if (fabs(k-all_end_data_C[i])>=1.E-6){
56  pass =0;
57  printf(" %lf %lf %lf %lf %lf\n",all_start_data_A[i],all_start_data_B[i],all_start_data_C[i],k,all_end_data_C[i]);
58  }
59  }
60  }
61  MPI_Allreduce(MPI_IN_PLACE, &pass, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
62 
63  if (dw.rank == 0){
64  if (pass){
65  printf("{ f3(A[\"ijkl\"], B[\"ijkl\"], C[\"ijkl\"]) } passed\n");
66  } else {
67  printf("{ f3(A[\"ijkl\"], B[\"ijkl\"], C[\"ijkl\"]) } failed\n");
68  }
69  }
70 
71  delete [] all_start_data_A;
72  delete [] all_start_data_B;
73  delete [] all_start_data_C;
74  delete [] all_end_data_C;
75 
76  return pass;
77 }
78 
79 
80 #ifndef TEST_SUITE
81 
82 char* getCmdOption(char ** begin,
83  char ** end,
84  const std::string & option){
85  char ** itr = std::find(begin, end, option);
86  if (itr != end && ++itr != end){
87  return *itr;
88  }
89  return 0;
90 }
91 
92 
93 int main(int argc, char ** argv){
94  int rank, np, n;
95  int const in_num = argc;
96  char ** input_str = argv;
97 
98  MPI_Init(&argc, &argv);
99  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
100  MPI_Comm_size(MPI_COMM_WORLD, &np);
101 
102  if (getCmdOption(input_str, input_str+in_num, "-n")){
103  n = atoi(getCmdOption(input_str, input_str+in_num, "-n"));
104  if (n < 0) n = 5;
105  } else n = 5;
106 
107 
108  {
109  World dw(MPI_COMM_WORLD, argc, argv);
110 
111  if (rank == 0){
112  printf("Computing bivar_transform A_ijkl = f(A_ijkl)\n");
113  }
114  bivar_transform(n, dw);
115  }
116 
117 
118  MPI_Finalize();
119  return 0;
120 }
121 
127 #endif
void f3(double a, double b, double &c)
int main(int argc, char **argv)
def rank(self)
Definition: core.pyx:312
void read_all(int64_t *npair, dtype **data, bool unpack=false)
collects the entire tensor data on each process (not memory scalable)
Definition: tensor.cxx:377
Definition: common.h:37
int bivar_transform(int n, World &dw)
an instance of the CTF library (world) on a MPI communicator
Definition: world.h:19
string
Definition: core.pyx:456
void fill_random(dtype rmin, dtype rmax)
fills local unique tensor elements to random values in the range [min,max] works only for dtype in {f...
Definition: tensor.cxx:928
int rank
rank of local processor
Definition: world.h:24
Definition: apsp.cxx:17
an instance of a tensor within a CTF world
Definition: tensor.h:74
char * getCmdOption(char **begin, char **end, const std::string &option)
def np(self)
Definition: core.pyx:315