00001 00005 template <class T, class S> class communicator 00006 { 00007 private: 00008 vector<T> _rpos; 00009 vector<S> _rsca; 00010 vector<T> _rcom; 00011 vector<T> _rcnt; 00012 vector<T> _rdsp; 00013 vector<S> _rvec; 00014 vector<S> _svec; 00015 vector<S> _rcol; 00016 public: 00021 void collect(S &_t) 00022 { 00023 network::allgather(&_t, sizeof(S), &_rcol[0], sizeof(S)); 00024 S s = 0.0; 00025 for(int i = 0; i < (int)_rcol.size(); i++) s += _rcol[i]; 00026 _t = s; 00027 } 00032 void collect(vector<S> &_t) 00033 { 00034 int m = (int)_t.size(); 00035 int n = (int)_rcnt.size(); 00036 _rcol.resize(n * m); 00037 network::allgather(&_t[0], m * sizeof(S), &_rcol[0], m * sizeof(S)); 00038 00039 S *r = &_rcol[0]; 00040 for(int i = 0; i < m; i++) 00041 { 00042 S s = 0.0; 00043 for(int j = 0; j < n; j++) s += r[m * j + i]; 00044 _t[i] = s; 00045 } 00046 00047 } 00052 void distribute(vector<S> &_x) 00053 { 00054 if(_rpos.size() == 0) return; 00055 S *x = &_x[0]; 00056 for(int i = 0; i < (int)_rpos.size(); i++) 00057 { 00058 x[_rpos[i]] *= _rsca[i]; 00059 } 00060 } 00065 void distribute(packed_vector<S> &_x) 00066 { 00067 if(_rpos.size() == 0) return; 00068 S *x = &_x[0]; 00069 S *s = &_rsca[0]; 00070 T *p = &_rpos[0]; 00071 int m = (int)_rpos.size(); 00072 int n = _x.numrhs() * _x.numdof(); 00073 for(int i = 0; i < m; i++) 00074 { 00075 T k = n * p[i]; 00076 S t = s[i]; 00077 for(int j = 0; j < n; j++) 00078 { 00079 x[k + j] *= t; 00080 } 00081 } 00082 } 00087 void accumulate(vector<S> &_x) 00088 { 00089 if(_rcom.size() == 0) return; 00090 for(int i = 0; i < (int)_rcom.size(); i++) _svec[i] = _x[_rcom[i]]; 00091 for(int i = 0; i < (int)_rcnt.size(); i++) _rcnt[i] *= sizeof(S), _rdsp[i] *= sizeof(S); 00092 network::alltoallv(&_svec[0], &_rcnt[0], &_rdsp[0], &_rvec[0], &_rcnt[0], &_rdsp[0]); 00093 for(int i = 0; i < (int)_rcnt.size(); i++) _rcnt[i] /= sizeof(S), _rdsp[i] /= sizeof(S); 00094 for(int i = 0; i < (int)_rcom.size(); i++) _x[_rcom[i]] += _rvec[i]; 00095 } 00100 void accumulate(packed_vector<S> &_x) 00101 { 00102 if(_rcom.size() == 0) return; 00103 int n = _x.numrhs() * _x.numdof(); 00104 _svec.resize(n * _rcom.size()); 00105 _rvec.resize(n * _rcom.size()); 00106 S *x = &_x[0], *s = &_svec[0], *r = &_rvec[0]; 00107 int m = (int)_rcom.size(); 00108 for(int i = 0; i < m; i++) 00109 { 00110 T k = n * i; 00111 T l = n * _rcom[i]; 00112 for(int j = 0; j < n; j++) 00113 { 00114 s[k + j] = x[l + j]; 00115 } 00116 } 00117 00118 for(int i = 0; i < (int)_rcnt.size(); i++) _rcnt[i] *= n * sizeof(S), _rdsp[i] *= n * sizeof(S); 00119 network::alltoallv(&_svec[0], &_rcnt[0], &_rdsp[0], &_rvec[0], &_rcnt[0], &_rdsp[0]); 00120 for(int i = 0; i < (int)_rcnt.size(); i++) _rcnt[i] /= n * sizeof(S), _rdsp[i] /= n * sizeof(S); 00121 00122 for(int i = 0; i < m; i++) 00123 { 00124 T k = n * i; 00125 T l = n * _rcom[i]; 00126 for(int j = 0; j < n; j++) 00127 { 00128 x[l + j] += r[k + j]; 00129 } 00130 } 00131 } 00136 communicator(const vector<T> &_gnod) 00137 { 00138 vector<T> _rnod(_gnod); 00139 int size, rank; 00140 network::size(size); 00141 network::rank(rank); 00142 _rcol.resize(size); 00143 00144 int rnod0 = (int)_rnod.size(); 00145 vector<T> rnod(rnod0); 00146 for(int i = 0; i < rnod0; i++) rnod[i] = i; 00147 binary_sort_copy(_rnod, rnod); 00148 00149 _rcnt.resize(size); 00150 network::allgather(&rnod0, sizeof(T), &_rcnt[0], sizeof(T)); 00151 int rcom0 = bucket_sort_size(_rcnt); 00152 _rcom.resize(rcom0); 00153 _rdsp.resize(size); 00154 bucket_sort_offset(_rcnt, _rdsp); 00155 00156 for(int i = 0; i < (int)_rcnt.size(); i++) _rcnt[i] *= sizeof(T), _rdsp[i] *= sizeof(T); 00157 network::allgatherv(&_rnod[0], rnod0 * sizeof(T), &_rcom[0], &_rcnt[0], &_rdsp[0]); 00158 for(int i = 0; i < (int)_rcnt.size(); i++) _rcnt[i] /= sizeof(T), _rdsp[i] /= sizeof(T); 00159 00160 global_intersection(size, rank, _rnod, rnod, _rcom, _rcnt, _rdsp); 00161 rcom0 = (int)_rcom.size(); 00162 _rvec.resize(rcom0); 00163 _svec.resize(rcom0); 00164 00165 _rpos.assign(_rcom.begin(), _rcom.end()); 00166 _rsca.resize(rcom0, 1.0); 00167 binary_sort(_rpos); 00168 unique_accumulate(_rpos, _rsca); 00169 for(int i = 0; i < (int)_rsca.size(); i++) 00170 { 00171 _rsca[i] = 1.0/(1.0 + _rsca[i]); 00172 } 00173 } 00174 00175 };