Cyclops Tensor Framework
parallel arithmetic on multidimensional arrays
sparse_permuted_slice.cxx
Go to the documentation of this file.
1 /*Copyright (c) 2011, Edgar Solomonik, all rights reserved.*/
9 #include <ctf.hpp>
10 using namespace CTF;
19  int b,
20  int sym,
21  World & dw){
22  int np, rank, pass, bi;
23  int64_t i, j, nvals;
24  int64_t * indices;
25  double * data;
26  int * perm;
27  int ** perms;
28 
29  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
30  MPI_Comm_size(MPI_COMM_WORLD, &np);
31 
32  perms = (int**)malloc(sizeof(int*)*2);
33 
34  srand(rank*13+7);
35 
36  //make each block have somewhat different size
37  bi = b + (rand()%b);
38 
39  perm = (int*)malloc(sizeof(int)*bi);
40  perms[0] = perm;
41  perms[1] = perm;
42 
43  //each block is random permuted symmetric submatrix
44  for (i=0; i<bi; i++){
45  int cont = 1;
46  while (cont){
47  perm[i] = rand()%n;
48  cont = 0;
49  for (j=0; j<i; j++){
50  if (perm[i] == perm[j]) cont = 1;
51  }
52  }
53  }
54 
55  Matrix<> A(n, n, sym, dw, "A");
56 
57  World id_world(MPI_COMM_SELF);
58 
59  Matrix<> B(bi, bi, sym, id_world, "B");
60 
61  B.get_local_data(&nvals, &indices, &data);
62 
63  srand48(rank*29+3);
64  for (i=0; i<nvals; i++){
65  data[i] = drand48();
66  }
67  B.write(nvals, indices, data);
68  free(indices);
69  delete [] data;
70 
71 
72  // this is the main command that does the sparse write
73 
74  double t_str, t_stp;
75  if (rank == 0)
76  t_str = MPI_Wtime();
77 
78  A.permute(1.0, B, perms, 1.0);
79  if (rank == 0){
80  t_stp = MPI_Wtime();
81  printf("permute took %lf sec\n", t_stp-t_str);
82  }
83 
84 
85  // Everything below is simply to test the above permute call,
86  // which is hard since there are overlapped writes
87 
88  int lens_Arep[3] = {n,n,np};
89  int symm[3] = {sym,NS,NS};
90  int lens_B3[3] = {bi,bi,1};
91 
92  Tensor<> A_rep(3, lens_Arep, symm, dw, "A_rep");
93  Tensor<> B3(3, lens_B3, symm, id_world, "B3");
94 
95  B3["ijk"] = B["ij"];
96 
97 
98  int ** perms_rep;
99 
100  perms_rep = (int**)malloc(sizeof(int*)*3);
101 
102  perms_rep[0] = perm;
103  perms_rep[1] = perm;
104  perms_rep[2] = &rank;
105 
106  // Writeinto a 3D tensor to avoid overlapped writes
107  A_rep.permute(1.0, B3, perms_rep, 1.0);
108  // Retrieve the data I wrote from B3 into A_rep back into callback_B3
109  Tensor<> callback_B3(3, lens_B3, symm, id_world, "cB3");
110  callback_B3.permute(perms_rep, 1.0, A_rep, 1.0);
111 
112 
113  // Check that B == callback_B3
114  callback_B3["ij"] = callback_B3["ij"] - B["ij"];
115  //callback_B3["ij"] -= B["ij"];
116 
117  pass = callback_B3.norm2() < 1.E-10;
118 
119  if (!pass){
120  if (rank == 0){
121  printf("Callback from permuted write returned incorrect values\n");
122  printf("{ sparse permuted slice among multiple worlds } failed\n");
123  }
124  return 0;
125  }
126 
127  // Check that if we sum over the replicated dimension we get the same thing
128  // as in the original sparse write
129  Matrix<> ERR(n, n, sym, dw);
130  ERR["ij"] = A_rep["ijk"] - A["ij"];
131 
132  pass = ERR.norm2() < 1.E-10;
133 
134  MPI_Allreduce(MPI_IN_PLACE, &pass, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
135 
136  if (rank == 0){
137  if (pass)
138  printf("{ sparse permuted slice among multiple worlds } passed\n");
139  else
140  printf("{ sparse permuted slice among multiple worlds } failed\n");
141  }
142  return pass;
143 }
144 
145 
146 #ifndef TEST_SUITE
147 char* getCmdOption(char ** begin,
148  char ** end,
149  const std::string & option){
150  char ** itr = std::find(begin, end, option);
151  if (itr != end && ++itr != end){
152  return *itr;
153  }
154  return 0;
155 }
156 
157 int main(int argc, char ** argv){
158  int rank, np, n, b;
159  int const in_num = argc;
160  char ** input_str = argv;
161 
162  MPI_Init(&argc, &argv);
163  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
164  MPI_Comm_size(MPI_COMM_WORLD, &np);
165 
166  if (getCmdOption(input_str, input_str+in_num, "-n")){
167  n = atoi(getCmdOption(input_str, input_str+in_num, "-n"));
168  if (n < 0) n = 256;
169  } else n = 256;
170 
171  if (getCmdOption(input_str, input_str+in_num, "-b")){
172  b = atoi(getCmdOption(input_str, input_str+in_num, "-b"));
173  if (b < 0) b = 16;
174  } else b = 16;
175 
176  {
177  World dw(MPI_COMM_WORLD, argc, argv);
178  int pass;
179  if (rank == 0){
180  printf("Testing nonsymmetric multiworld permutation with n=%d\n",n);
181  }
182  pass = sparse_permuted_slice(n, b, NS, dw);
183  assert(pass);
184  if (rank == 0){
185  printf("Testing symmetric multiworld permutation with n=%d\n",n);
186  }
187  pass = sparse_permuted_slice(n, b, SY, dw);
188  assert(pass);
189  if (rank == 0){
190  printf("Testing symmetric-hollow multiworld permutation with n=%d\n",n);
191  }
192  pass = sparse_permuted_slice(n, b, SH, dw);
193  assert(pass);
194  if (rank == 0){
195  printf("Testing asymmetric multiworld permutation with n=%d\n",n);
196  }
197  pass = sparse_permuted_slice(n, b, AS, dw);
198  assert(pass);
199  }
200 
201  MPI_Finalize();
202  return 0;
203 }
204 
210 #endif
int sparse_permuted_slice(int n, int b, int sym, World &dw)
tests sparse remote global write via permute function
Matrix class which encapsulates a 2D tensor.
Definition: matrix.h:18
def rank(self)
Definition: core.pyx:312
void permute(dtype beta, CTF_int::tensor &A, int *const *perms_A, dtype alpha)
Apply permutation to matrix, potentially extracting a slice B[i,j,...] = beta*B[...] + alpha*A[perms_A[0][i],perms_A[1][j],...].
Definition: tensor.cxx:429
Definition: common.h:37
an instance of the CTF library (world) on a MPI communicator
Definition: world.h:19
string
Definition: core.pyx:456
dtype norm2()
computes the frobenius norm of the tensor (needs sqrt()!)
Definition: tensor.h:811
char * getCmdOption(char **begin, char **end, const std::string &option)
int main(int argc, char **argv)
void get_local_data(int64_t *npair, int64_t **global_idx, dtype **data, bool nonzeros_only=false, bool unpack_sym=false) const
Gives the global indices and values associated with the local data.
Definition: tensor.cxx:159
Definition: apsp.cxx:17
an instance of a tensor within a CTF world
Definition: tensor.h:74
Definition: common.h:37
Definition: common.h:37
void write(int64_t npair, int64_t const *global_idx, dtype const *data)
writes in values associated with any set of indices The sparse data is defined in coordinate format...
Definition: tensor.cxx:264
Definition: common.h:37
def np(self)
Definition: core.pyx:315