📄 distvect.cc
字号:
//// distvect.cc//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Curtis Janssen <cljanss@limitpt.com>// Maintainer: LPS//// This file is part of the SC Toolkit.//// The SC Toolkit is free software; you can redistribute it and/or modify// it under the terms of the GNU Library General Public License as published by// the Free Software Foundation; either version 2, or (at your option)// any later version.//// The SC Toolkit is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU Library General Public License for more details.//// You should have received a copy of the GNU Library General Public License// along with the SC Toolkit; see the file COPYING.LIB. If not, write to// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.//// The U.S. Government is granted a limited license as per AL 91-7.//#include <iostream>#include <iomanip>#include <math.h>#include <util/misc/formio.h>#include <util/keyval/keyval.h>#include <math/scmat/dist.h>#include <math/scmat/cmatrix.h>#include <math/scmat/elemop.h>using namespace std;using namespace sc;/////////////////////////////////////////////////////////////////////////////// DistSCVector member functionsstatic ClassDesc DistSCVector_cd( typeid(DistSCVector),"DistSCVector",1,"public SCVector", 0, 0, 0);DistSCVector::DistSCVector(const RefSCDimension&a, DistSCMatrixKit*k): SCVector(a,k){ init_blocklist();}intDistSCVector::block_to_node(int i) const{ return (i)%messagegrp()->n();}Ref<SCMatrixBlock>DistSCVector::block_to_block(int i) const{ int offset = i; int nproc = messagegrp()->n(); if ((offset%nproc) != messagegrp()->me()) return 0; SCMatrixBlockListIter I; for (I=blocklist->begin(); I!=blocklist->end(); I++) { if (I.block()->blocki == i) return I.block(); } ExEnv::errn() << indent << "DistSCVector::block_to_block: internal error" << endl; abort(); return 0;}double *DistSCVector::find_element(int i) const{ int bi, oi; d->blocks()->elem_to_block(i, bi, oi); Ref<SCVectorSimpleBlock> blk; blk << block_to_block(bi); if (blk.nonnull()) { return &blk->dat()[oi]; } else { return 0; }}intDistSCVector::element_to_node(int i) const{ int bi, oi; d->blocks()->elem_to_block(i, bi, oi); return block_to_node(bi);}voidDistSCVector::init_blocklist(){ int i; int nproc = messagegrp()->n(); int me = messagegrp()->me(); blocklist = new SCMatrixBlockList; SCMatrixBlock *b; for (i=0; i<d->blocks()->nblock(); i++) { if (i%nproc != me) continue; b = new SCVectorSimpleBlock(d->blocks()->start(i), d->blocks()->fence(i)); b->blocki = i; blocklist->insert(b); }}DistSCVector::~DistSCVector(){}doubleDistSCVector::get_element(int i) const{ double res; double *e = find_element(i); if (e) { res = *e; messagegrp()->bcast(res, messagegrp()->me()); } else { messagegrp()->bcast(res, element_to_node(i)); } return res;}voidDistSCVector::set_element(int i,double a){ double *e = find_element(i); if (e) { *e = a; }}voidDistSCVector::accumulate_element(int i,double a){ double *e = find_element(i); if (e) { *e += a; }}voidDistSCVector::accumulate(const SCVector*a){ // make sure that the argument is of the correct type const DistSCVector* la = require_dynamic_cast<const DistSCVector*>(a,"DistSCVector::accumulate"); // make sure that the dimensions match if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "DistSCVector::accumulate(SCVector*a): " << "dimensions don't match\n"; abort(); } SCMatrixBlockListIter i1, i2; for (i1=la->blocklist->begin(),i2=blocklist->begin(); i1!=la->blocklist->end() && i2!=blocklist->end(); i1++,i2++) { int n = i1.block()->ndat(); if (n != i2.block()->ndat()) { ExEnv::errn() << indent << "DistSCVector::accumulate " << "mismatch: internal error" << endl; abort(); } double *dat1 = i1.block()->dat(); double *dat2 = i2.block()->dat(); for (int i=0; i<n; i++) { dat2[i] += dat1[i]; } }}voidDistSCVector::accumulate(const SCMatrix*a){ // make sure that the argument is of the correct type const DistSCMatrix* la = require_dynamic_cast<const DistSCMatrix*>(a,"DistSCVector::accumulate"); // make sure that the dimensions match if (!((la->rowdim()->equiv(dim()) && la->coldim()->n() == 1) || (la->coldim()->equiv(dim()) && la->rowdim()->n() == 1))) { ExEnv::errn() << indent << "DistSCVector::accumulate(SCMatrix*a): " << "dimensions don't match\n"; abort(); } SCMatrixBlockListIter I, J; for (I = la->blocklist->begin(), J = blocklist->begin(); I != la->blocklist->end() && J != blocklist->end(); I++,J++) { int n = I.block()->ndat(); if (n != J.block()->ndat()) { ExEnv::errn() << indent << "DistSCVector::accumulate(SCMatrix*a): " << "block lists do not match" << endl; abort(); } double *dati = I.block()->dat(); double *datj = J.block()->dat(); for (int i=0; i<n; i++) datj[i] += dati[i]; }}voidDistSCVector::assign_v(SCVector*a){ // make sure that the argument is of the correct type DistSCVector* la = require_dynamic_cast<DistSCVector*>(a,"DistSCVector::assign_v"); // make sure that the dimensions match if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "DistSCVector::assign_v(SCVector*a): " << "dimensions don't match\n"; abort(); } SCMatrixBlockListIter i1, i2; for (i1=la->blocklist->begin(),i2=blocklist->begin(); i1!=la->blocklist->end() && i2!=blocklist->end(); i1++,i2++) { int n = i1.block()->ndat(); if (n != i2.block()->ndat()) { ExEnv::errn() << indent << "DistSCVector::assign " << "mismatch: internal error" << endl; abort(); } double *dat1 = i1.block()->dat(); double *dat2 = i2.block()->dat(); for (int i=0; i<n; i++) { dat2[i] = dat1[i]; } }}voidDistSCVector::assign_p(const double*a){ SCMatrixBlockListIter I; for (I=blocklist->begin(); I!=blocklist->end(); I++) { Ref<SCVectorSimpleBlock> b = dynamic_cast<SCVectorSimpleBlock*>(I.block()); if (b.null()) { ExEnv::errn() << indent << "DistSCVector::assign " << "mismatch: internal error" << endl; abort(); } int n = b->ndat(); const double *dat1 = &a[b->istart]; double *dat2 = b->dat(); for (int i=0; i<n; i++) { dat2[i] = dat1[i]; } }}doubleDistSCVector::scalar_product(SCVector*a){ // make sure that the argument is of the correct type DistSCVector* la = require_dynamic_cast<DistSCVector*>(a,"DistSCVector::scalar_product"); // make sure that the dimensions match if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "DistSCVector::scalar_product(SCVector*a): " << "dimensions don't match\n"; abort(); } double result = 0.0; SCMatrixBlockListIter i1, i2; for (i1=la->blocklist->begin(),i2=blocklist->begin(); i1!=la->blocklist->end() && i2!=blocklist->end(); i1++,i2++) { int n = i1.block()->ndat(); if (n != i2.block()->ndat()) { ExEnv::errn() << indent << "DistSCVector::scalar_product: block mismatch: " << "internal error" << endl; abort(); } double *dat1 = i1.block()->dat(); double *dat2 = i2.block()->dat(); for (int i=0; i<n; i++) { result += dat2[i] * dat1[i]; } } messagegrp()->sum(result); return result;}voidDistSCVector::element_op(const Ref<SCElementOp>& op){ SCMatrixBlockListIter i; for (i = blocklist->begin(); i != blocklist->end(); i++) { op->process_base(i.block()); } if (op->has_collect()) op->collect(messagegrp());}voidDistSCVector::element_op(const Ref<SCElementOp2>& op, SCVector* m){ DistSCVector *lm = require_dynamic_cast<DistSCVector*>(m, "DistSCVector::element_op"); if (!dim()->equiv(lm->dim())) { ExEnv::errn() << indent << "DistSCVector: bad element_op\n"; abort(); } SCMatrixBlockListIter i, j; for (i = blocklist->begin(), j = lm->blocklist->begin(); i != blocklist->end(); i++, j++) { op->process_base(i.block(), j.block()); } if (op->has_collect()) op->collect(messagegrp());}voidDistSCVector::element_op(const Ref<SCElementOp3>& op, SCVector* m,SCVector* n){ DistSCVector *lm = require_dynamic_cast<DistSCVector*>(m, "DistSCVector::element_op"); DistSCVector *ln = require_dynamic_cast<DistSCVector*>(n, "DistSCVector::element_op"); if (!dim()->equiv(lm->dim()) || !dim()->equiv(ln->dim())) { ExEnv::errn() << indent << "DistSCVector: bad element_op\n"; abort(); } SCMatrixBlockListIter i, j, k; for (i = blocklist->begin(), j = lm->blocklist->begin(), k = ln->blocklist->begin(); i != blocklist->end(); i++, j++, k++) { op->process_base(i.block(), j.block(), k.block()); } if (op->has_collect()) op->collect(messagegrp());}voidDistSCVector::accumulate_product_rv(SCMatrix *pa, SCVector *pb){ const char* name = "DistSCMatrix::accumulate_product_rv"; // make sure that the arguments are of the correct type DistSCMatrix* a = require_dynamic_cast<DistSCMatrix*>(pa,name); DistSCVector* b = require_dynamic_cast<DistSCVector*>(pb,name); // make sure that the dimensions match if (!dim()->equiv(a->rowdim()) || !a->coldim()->equiv(b->dim())) { ExEnv::errn() << indent << "DistSCVector::accumulate_product_rv(SCMatrix*a,SCVector*b): " << "dimensions don't match\n"; abort(); } a->create_vecform(DistSCMatrix::Row); a->vecform_op(DistSCMatrix::CopyToVec); int n = dim()->n(); double *res = new double[n]; for (int i=0; i<n; i++) res[i] = 0.0; Ref<SCMatrixSubblockIter> I = b->all_blocks(SCMatrixSubblockIter::Read); for (I->begin(); I->ready(); I->next()) { Ref<SCVectorSimpleBlock> blk = dynamic_cast<SCVectorSimpleBlock*>(I->block()); int n = blk->iend - blk->istart; int joff = blk->istart; double *data = blk->data; for (int i=0; i<a->nvec; i++) { double *aveci = a->vec[i]; for (int j=0; j<n; j++) { res[i+a->vecoff] += aveci[j+joff]*data[j]; } } } a->delete_vecform(); messagegrp()->sum(res, n); I = local_blocks(SCMatrixSubblockIter::Accum); for (I->begin(); I->ready(); I->next()) { Ref<SCVectorSimpleBlock> blk = dynamic_cast<SCVectorSimpleBlock*>(I->block()); int n = blk->iend - blk->istart; int ioff = blk->istart; double *data = blk->data; for (int i=0; i<n; i++) { data[i] += res[i+ioff]; } } I = 0; delete[] res;}voidDistSCVector::convert(double *res) const{ int n = dim()->n(); for (int i=0; i<n; i++) res[i] = 0.0; Ref<SCMatrixSubblockIter> I = ((DistSCVector*)this)->local_blocks(SCMatrixSubblockIter::Read); for (I->begin(); I->ready(); I->next()) { Ref<SCVectorSimpleBlock> blk = dynamic_cast<SCVectorSimpleBlock*>(I->block()); int ni = blk->iend - blk->istart; int ioff = blk->istart; double *data = blk->data; for (int i=0; i<ni; i++) { res[i+ioff] = data[i]; } } messagegrp()->sum(res, n);}voidDistSCVector::convert(SCVector *v){ SCVector::convert(v);}Ref<SCMatrixSubblockIter>DistSCVector::local_blocks(SCMatrixSubblockIter::Access access){ return new SCMatrixListSubblockIter(access, blocklist);}Ref<SCMatrixSubblockIter>DistSCVector::all_blocks(SCMatrixSubblockIter::Access access){ return new DistSCMatrixListSubblockIter(access, blocklist, messagegrp());}voidDistSCVector::vprint(const char *title, ostream& os, int prec) const{ double *data = new double[dim()->n()]; convert(data); int i; int lwidth; double max=this->maxabs(); max = (max==0.0) ? 1.0 : log10(max); if (max < 0.0) max=1.0; lwidth = prec+5+(int) max; os.setf(ios::fixed,ios::floatfield); os.precision(prec); os.setf(ios::right,ios::adjustfield); if (messagegrp()->me() == 0) { if (title) os << endl << indent << title << endl; else os << endl; if (n()==0) { os << indent << "empty vector\n"; return; } for (i=0; i<n(); i++) os << indent << setw(5) << i+1 << setw(lwidth) << data[i] << endl; os << endl; os.flush(); } delete[] data;}voidDistSCVector::error(const char *msg){ ExEnv::errn() << indent << "DistSCVector: error: " << msg << endl;}Ref<DistSCMatrixKit>DistSCVector::skit(){ return dynamic_cast<DistSCMatrixKit*>(kit().pointer());}/////////////////////////////////////////////////////////////////////////////// Local Variables:// mode: c++// c-file-style: "CLJ"// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -