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 };