16 #include "Zoltan2_config.h"
21 #include <Teuchos_RCP.hpp>
22 #include <Teuchos_ArrayView.hpp>
23 #include <Teuchos_ParameterList.hpp>
24 #include <Teuchos_DefaultComm.hpp>
25 #include <Teuchos_Comm.hpp>
26 #include <Teuchos_CommHelpers.hpp>
29 #include <Tpetra_MultiVector.hpp>
30 #include <Tpetra_KokkosCompat_DefaultNode.hpp>
44 using Teuchos::ArrayView;
45 using Teuchos::CommandLineProcessor;
47 typedef Tpetra::MultiVector<zscalar_t, zlno_t, zgno_t, znode_t>
tMVector_t;
48 typedef Tpetra::Map<zlno_t, zgno_t, znode_t>
tMap_t;
62 const string& delimiters =
" \f\n\r\t\v" )
64 return s.substr( 0, s.find_last_not_of( delimiters ) + 1 );
69 const string& delimiters =
" \f\n\r\t\v" )
71 return s.substr( s.find_first_not_of( delimiters ) );
76 const string& delimiters =
" \f\n\r\t\v" )
81 void readGeoGenParams(
string paramFileName, Teuchos::ParameterList &geoparams,
const RCP<
const Teuchos::Comm<int> > & comm){
82 std::string input =
"";
84 for(
int i = 0; i < 25000; ++i){
89 if(comm->getRank() == 0){
91 std::fstream inParam(paramFileName.c_str());
99 getline (inParam,tmp);
100 while (!inParam.eof()){
107 getline (inParam,tmp);
110 for (
size_t i = 0; i < input.size(); ++i){
118 int size = input.size();
122 comm->broadcast(0,
sizeof(
int), (
char*) &size);
124 throw "File " + paramFileName +
" cannot be opened.";
126 comm->broadcast(0, size, inp);
127 std::istringstream inParam(inp);
129 getline (inParam,str);
130 while (!inParam.eof()){
132 size_t pos = str.find(
'=');
133 if(pos == string::npos){
134 throw "Invalid Line:" + str +
" in parameter file";
136 string paramname =
trim_copy(str.substr(0,pos));
137 string paramvalue =
trim_copy(str.substr(pos + 1));
138 geoparams.set(paramname, paramvalue);
140 getline (inParam,str);
167 ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
168 int num_wgts,
float *obj_wgts,
int *ierr)
173 size_t localLen = dots->
coordinates->getLocalLength();
175 dots->
coordinates->getMap()->getLocalElementList().getRawPtr();
177 if (
sizeof(ZOLTAN_ID_TYPE) ==
sizeof(
zgno_t))
178 memcpy(gids, ids,
sizeof(ZOLTAN_ID_TYPE) * localLen);
180 for (
size_t i=0; i < localLen; i++)
181 gids[i] = static_cast<ZOLTAN_ID_TYPE>(ids[i]);
184 float *wgts = obj_wgts;
185 for (
size_t i=0; i < localLen; i++)
186 for (
int w=0; w < num_wgts; w++)
193 int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
194 int dim,
double *coords,
int *ierr)
200 double *val = coords;
204 for (
int i=0; i < numObj; i++){
205 *val++ =
static_cast<double>(x[i]);
206 *val++ =
static_cast<double>(y[i]);
207 *val++ =
static_cast<double>(z[i]);
213 double *val = coords;
216 for (
int i=0; i < numObj; i++){
217 *val++ =
static_cast<double>(x[i]);
218 *val++ =
static_cast<double>(y[i]);
236 const RCP<
const Teuchos::Comm<int> > & comm,
237 vector<float> &wgts,
weightTypes how,
float scale,
int rank)
241 float val = scale + rank%2;
242 for (
zlno_t i=0; i < len; i++)
246 for (
int i=0; i < 10; i++){
247 float val = (i + 10)*scale;
248 for (
zlno_t j=i; j < len; j += 10)
253 float val = scale + rank;
254 for (
zlno_t i=0; i < len; i++)
265 const RCP<
const Teuchos::Comm<int> > & comm,
268 int rank = comm->getRank();
269 int nprocs = comm->getSize();
271 double k = log(numGlobalCoords) / 3;
272 double xdimf = exp(k) + 0.5;
273 ssize_t xdim =
static_cast<ssize_t
>(floor(xdimf));
275 ssize_t zdim = numGlobalCoords / (xdim*ydim);
276 ssize_t num=xdim*ydim*zdim;
277 ssize_t diff = numGlobalCoords - num;
281 if (zdim > xdim && zdim > ydim){
283 newdiff = diff - (xdim*ydim);
288 else if (ydim > xdim && ydim > zdim){
290 newdiff = diff - (xdim*zdim);
297 newdiff = diff - (ydim*zdim);
307 diff = numGlobalCoords - num;
309 diff /= -numGlobalCoords;
311 diff /= numGlobalCoords;
315 std::cout <<
"Warning: Difference " << diff*100 <<
" percent" << std::endl;
316 std::cout <<
"Mesh size: " << xdim <<
"x" << ydim <<
"x" <<
317 zdim <<
", " << num <<
" vertices." << std::endl;
322 ssize_t numLocalCoords = num / nprocs;
323 ssize_t leftOver = num % nprocs;
326 if (rank <= leftOver)
327 gid0 = rank * (numLocalCoords+1);
329 gid0 = (leftOver * (numLocalCoords+1)) +
330 ((rank - leftOver) * numLocalCoords);
335 ssize_t gid1 = gid0 + numLocalCoords;
340 ArrayView<zgno_t> idArray(ids, numLocalCoords);
343 for (ssize_t i=gid0; i < gid1; i++)
346 RCP<const tMap_t> idMap = rcp(
new tMap_t(num, idArray, 0, comm));
353 if (!x)
throw bad_alloc();
360 zgno_t xyPlane = xdim*ydim;
361 zgno_t zStart = gid0 / xyPlane;
362 zgno_t rem = gid0 % xyPlane;
369 for (
zscalar_t zval=zStart; next < numLocalCoords && zval < zdim; zval+=1.){
370 for (
zscalar_t yval=yStart; next < numLocalCoords && yval < ydim; yval+=1.){
371 for (
zscalar_t xval=xStart; next < numLocalCoords && xval < xdim;xval+=1.){
382 ArrayView<const zscalar_t> xArray(x, numLocalCoords*3);
390 int main(
int narg,
char *arg[])
394 Tpetra::ScopeGuard tscope(&narg, &arg);
395 Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
396 int rank = comm->getRank();
397 int nprocs = comm->getSize();
400 MEMORY_CHECK(rank==0 || rank==nprocs-1,
"After initializing MPI");
403 std::cout <<
"Number of processes: " << nprocs << std::endl;
406 zgno_t numGlobalCoords = 1000;
409 string memoryOn(
"memoryOn");
410 string memoryOff(
"memoryOff");
412 int numGlobalParts = nprocs;
416 string balanceCount(
"balance_object_count");
417 string balanceWeight(
"balance_object_weight");
418 string mcnorm1(
"multicriteria_minimize_total_weight");
419 string mcnorm2(
"multicriteria_balance_total_maximum");
420 string mcnorm3(
"multicriteria_minimize_maximum_weight");
421 string objective(balanceWeight);
424 CommandLineProcessor commandLine(
false,
true);
427 int input_option = 0;
428 commandLine.setOption(
"input_option", &input_option,
429 "whether to use mesh creation, geometric generator, or file input");
430 string inputFile =
"";
432 commandLine.setOption(
"input_file", &inputFile,
433 "the input file for geometric generator or file input");
436 commandLine.setOption(
"size", &numGlobalCoords,
437 "Approximate number of global coordinates.");
438 commandLine.setOption(
"numParts", &numGlobalParts,
439 "Number of parts (default is one per proc).");
440 commandLine.setOption(
"nWeights", &nWeights,
441 "Number of weights per coordinate, zero implies uniform weights.");
442 commandLine.setOption(
"debug", &debugLevel,
"Zoltan1 debug level");
443 commandLine.setOption(
"remap",
"no-remap", &remap,
444 "Zoltan1 REMAP parameter; disabled by default for scalability testing");
445 commandLine.setOption(
"timers", &dummyTimer,
"ignored");
446 commandLine.setOption(memoryOn.c_str(), memoryOff.c_str(), &doMemory,
447 "do memory profiling");
449 string doc(balanceCount);
450 doc.append(
": ignore weights\n");
451 doc.append(balanceWeight);
452 doc.append(
": balance on first weight\n");
454 doc.append(
": given multiple weights, balance their total.\n");
456 doc.append(
": given multiple weights, "
457 "balance the maximum for each coordinate.\n");
459 doc.append(
": given multiple weights, balance the L2 norm of the weights.\n");
460 commandLine.setOption(
"objective", &objective, doc.c_str());
462 CommandLineProcessor::EParseCommandLineReturn rc =
463 commandLine.parse(narg, arg);
467 if (rc != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
468 if (rc == Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED) {
469 if (rank==0) std::cout <<
"PASS" << std::endl;
473 if (rank==0) std::cout <<
"FAIL" << std::endl;
481 size_t numLocalCoords = 0;
482 if (input_option == 0){
484 numLocalCoords = dots.
coordinates->getLocalLength();
488 for (
int p=0; p < nprocs; p++){
490 std::cout <<
"Rank " << rank <<
", " << numLocalCoords <<
"coords" << std::endl;
494 for (
zlno_t i=0; i < numLocalCoords; i++)
495 std::cout <<
" " << x[i] <<
" " << y[i] <<
" " << z[i] << std::endl;
508 for (
int i=0; i < nWeights; i++){
509 dots.
weights[i].resize(numLocalCoords);
519 else if(input_option == 1){
520 Teuchos::ParameterList geoparams(
"geo params");
529 for(
int i = 0; i < coord_dim; ++i){
530 coords[i] =
new zscalar_t[numLocalCoords];
536 for(
int i = 0; i < nWeights; ++i){
537 weight[i] =
new zscalar_t[numLocalCoords];
544 RCP<Tpetra::Map<zlno_t, zgno_t, znode_t> > mp = rcp(
545 new Tpetra::Map<zlno_t, zgno_t, znode_t> (numGlobalCoords, numLocalCoords, 0, comm));
547 Teuchos::Array<Teuchos::ArrayView<const zscalar_t> > coordView(coord_dim);
548 for (
int i=0; i < coord_dim; i++){
549 if(numLocalCoords > 0){
550 Teuchos::ArrayView<const zscalar_t> a(coords[i], numLocalCoords);
553 Teuchos::ArrayView<const zscalar_t> a;
564 for (
int i = 0; i < nWeights;++i){
566 dots.
weights[i].push_back(weight[i][j]);
571 for(
int i = 0; i < nWeights; ++i)
582 numLocalCoords = coords->getLocalLength();
583 numGlobalCoords = coords->getGlobalLength();
586 MEMORY_CHECK(doMemory && rank==0,
"After creating input");
591 int aok = Zoltan_Initialize(narg, arg, &ver);
594 printf(
"Zoltan_Initialize failed\n");
598 struct Zoltan_Struct *zz;
599 zz = Zoltan_Create(MPI_COMM_WORLD);
601 Zoltan_Set_Param(zz,
"LB_METHOD",
"RCB");
602 Zoltan_Set_Param(zz,
"LB_APPROACH",
"PARTITION");
603 Zoltan_Set_Param(zz,
"CHECK_GEOM",
"0");
604 Zoltan_Set_Param(zz,
"NUM_GID_ENTRIES",
"1");
605 Zoltan_Set_Param(zz,
"NUM_LID_ENTRIES",
"0");
606 Zoltan_Set_Param(zz,
"RETURN_LISTS",
"PART");
607 std::ostringstream oss;
608 oss << numGlobalParts;
609 Zoltan_Set_Param(zz,
"NUM_GLOBAL_PARTS", oss.str().c_str());
612 Zoltan_Set_Param(zz,
"DEBUG_LEVEL", oss.str().c_str());
615 Zoltan_Set_Param(zz,
"REMAP",
"1");
617 Zoltan_Set_Param(zz,
"REMAP",
"0");
619 if (objective != balanceCount){
622 Zoltan_Set_Param(zz,
"OBJ_WEIGHT_DIM", oss.str().c_str());
624 if (objective == mcnorm1)
625 Zoltan_Set_Param(zz,
"RCB_MULTICRITERIA_NORM",
"1");
626 else if (objective == mcnorm2)
627 Zoltan_Set_Param(zz,
"RCB_MULTICRITERIA_NORM",
"2");
628 else if (objective == mcnorm3)
629 Zoltan_Set_Param(zz,
"RCB_MULTICRITERIA_NORM",
"3");
632 Zoltan_Set_Param(zz,
"OBJ_WEIGHT_DIM",
"0");
635 Zoltan_Set_Num_Obj_Fn(zz,
getNumObj, &dots);
636 Zoltan_Set_Obj_List_Fn(zz,
getObjList, &dots);
637 Zoltan_Set_Num_Geom_Fn(zz,
getDim, &dots);
638 Zoltan_Set_Geom_Multi_Fn(zz,
getCoords, &dots);
640 int changes, numGidEntries, numLidEntries, numImport, numExport;
641 ZOLTAN_ID_PTR importGlobalGids, importLocalGids;
642 ZOLTAN_ID_PTR exportGlobalGids, exportLocalGids;
643 int *importProcs, *importToPart, *exportProcs, *exportToPart;
645 MEMORY_CHECK(doMemory && rank==0,
"Before Zoltan_LB_Partition");
647 if (rank == 0) std::cout <<
"Calling Zoltan_LB_Partition" << std::endl;
648 aok = Zoltan_LB_Partition(zz, &changes, &numGidEntries, &numLidEntries,
649 &numImport, &importGlobalGids, &importLocalGids,
650 &importProcs, &importToPart,
651 &numExport, &exportGlobalGids, &exportLocalGids,
652 &exportProcs, &exportToPart);
653 if (rank == 0) std::cout <<
"Returned from Zoltan_LB_Partition" << std::endl;
655 MEMORY_CHECK(doMemory && rank==0,
"After Zoltan_LB_Partition");
659 float *sumWgtPerPart =
new float[numGlobalParts];
660 float *gsumWgtPerPart =
new float[numGlobalParts];
661 for (
int i = 0; i < numGlobalParts; i++) sumWgtPerPart[i] = 0.;
663 for (
size_t i = 0; i < numLocalCoords; i++)
664 sumWgtPerPart[exportToPart[i]] += (nWeights ? dots.
weights[0][i]: 1.);
666 Teuchos::reduceAll<int, float>(*comm, Teuchos::REDUCE_SUM, numGlobalParts,
667 sumWgtPerPart, gsumWgtPerPart);
669 float maxSumWgtPerPart = 0.;
670 float minSumWgtPerPart = std::numeric_limits<float>::max();
672 int maxSumWgtPart=0, minSumWgtPart=0;
673 for (
int i = 0; i < numGlobalParts; i++) {
674 if (gsumWgtPerPart[i] > maxSumWgtPerPart) {
675 maxSumWgtPerPart = gsumWgtPerPart[i];
678 if (gsumWgtPerPart[i] < minSumWgtPerPart) {
679 minSumWgtPerPart = gsumWgtPerPart[i];
682 totWgt += gsumWgtPerPart[i];
686 std::cout << std::endl << std::endl
687 <<
"Part loads (per part for " << numGlobalParts <<
" parts):"
689 <<
" min = " << minSumWgtPerPart
690 <<
" in part " << minSumWgtPart << std::endl
691 <<
" max = " << maxSumWgtPerPart
692 <<
" in part " << maxSumWgtPart << std::endl
693 <<
" tot = " << totWgt << std::endl
694 <<
" avg = " << totWgt / numGlobalParts
695 << std::endl << std::endl << std::endl;
697 delete [] sumWgtPerPart;
698 delete [] gsumWgtPerPart;
701 MEMORY_CHECK(doMemory && rank==0,
"After Zoltan_Destroy");
704 for (
int i = 0; i < nWeights; i++)
708 MEMORY_CHECK(doMemory && rank==0,
"After destroying input");
712 std::cout <<
"FAIL" << std::endl;
714 std::cout <<
"PASS" << std::endl;
void getCoords(void *data, int numGid, int numLid, int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids, int dim, double *coords_, int *ierr)
void getLocalCoordinatesCopy(scalar_t **c)
string trim_right_copy(const string &s, const string &delimiters=" \f\n\r\t\v")
void readGeoGenParams(string paramFileName, Teuchos::ParameterList &geoparams, const RCP< const Teuchos::Comm< int > > &comm)
int getCoordinateDimension()
int main(int narg, char **arg)
common code used by tests
string trim_copy(const string &s, const string &delimiters=" \f\n\r\t\v")
int getNumObj(void *data, int *ierr)
int getDim(void *data, int *ierr)
vector< vector< float > > weights
void getObjList(void *data, int numGid, int numLid, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids, int num_wgts, float *obj_wgts, int *ierr)
Tpetra::Map::local_ordinal_type zlno_t
static const std::string fail
string trim_left_copy(const string &s, const string &delimiters=" \f\n\r\t\v")
int getNumWeights()
##END Predistribution functions######################//
lno_t getNumLocalCoords()
gno_t getNumGlobalCoords()
A gathering of useful namespace methods.
Tpetra::Map::node_type znode_t
Tpetra::MultiVector< zscalar_t, zlno_t, zgno_t, znode_t > tMVector_t
Tpetra::Map::global_ordinal_type zgno_t
void getLocalWeightsCopy(scalar_t **w)
#define MEMORY_CHECK(iPrint, msg)
std::string testDataFilePath(".")