void Config::_registerModels() { // Register distribution helpers on each config run const bool createDist = _modelDist.empty(); //first run, create distributors const size_t nModels = _models.size(); LBASSERT( createDist || _modelDist.size() == nModels ); for( size_t i = 0; i < nModels; ++i ) { const Model* model = _models[i]; ModelDist* modelDist = 0; if( createDist ) { modelDist = new ModelDist( model ); _modelDist.push_back( modelDist ); } else modelDist = _modelDist[i]; modelDist->registerTree( getClient( )); LBASSERT( modelDist->isAttached() ); _frameData.setModelID( modelDist->getID( )); } LBASSERT( _modelDist.size() == nModels ); if( !_modelDist.empty( )) { ModelAssigner assigner( _modelDist ); accept( assigner ); } }
int main(int argc, char* argv[]) { diy::mpi::environment env(argc, argv); // diy equivalent of MPI_Init diy::mpi::communicator world; // diy equivalent of MPI communicator int size = 8; // total number of MPI processes int nblocks = 32; // total number of blocks in global domain diy::ContiguousAssigner assigner(size, nblocks); Bounds domain; // global data size domain.min[0] = domain.min[1] = domain.min[2] = 0; domain.max[0] = domain.max[1] = domain.max[2] = 255; int rank = world.rank(); // MPI rank of this process std::cout << "Rank " << rank << ":" << std::endl; diy::Master master(world, 1, // one thread -1, // all blocks in memory &Block::create, &Block::destroy); AddBlock addblock(master); // object for adding new blocks to master // share_face is an n-dim (size 3 in this example) vector of bools // indicating whether faces are shared in each dimension // uninitialized values default to false diy::RegularDecomposer<Bounds>::BoolVector share_face; share_face.push_back(true); // wrap is an n-dim (size 3 in this example) vector of bools // indicating whether boundary conditions are periodic in each dimension // uninitialized values default to false diy::RegularDecomposer<Bounds>::BoolVector wrap; wrap.push_back(true); wrap.push_back(true); // ghosts is an n-dim (size 3 in this example) vector of ints // indicating number of ghost cells per side in each dimension // uninitialized values default to 0 diy::RegularDecomposer<Bounds>::CoordinateVector ghosts; ghosts.push_back(1); ghosts.push_back(2); // either create the regular decomposer and call its decompose function // (having the decomposer available is useful for its other member functions diy::RegularDecomposer<Bounds> decomposer(3, domain, assigner, share_face, wrap, ghosts); decomposer.decompose(rank, addblock); // or combine the two lines above into the following helper function // but the decomposer gets destroyed afterwards // diy::decompose(3, rank, domain, assigner, addblock, share_face, wrap, ghosts); // display the decomposition master.foreach(&Block::show_link); }
inline void apply(InputGeometry const& geometry, partitions& state) const { // First pass. // Get min/max (in most cases left / right) points // This makes use of the geometry::less/greater predicates // For the left boundary it is important that multiple points // are sorted from bottom to top. Therefore the less predicate // does not take the x-only template parameter (this fixes ticket #6019. // For the right boundary it is not necessary (though also not harmful), // because points are sorted from bottom to top in a later stage. // For symmetry and to get often more balanced lower/upper halves // we keep it. typedef typename geometry::detail::range_type<InputGeometry>::type range_type; typedef typename boost::range_iterator < range_type const >::type range_iterator; detail::get_extremes < range_type, range_iterator, geometry::less<point_type>, geometry::greater<point_type> > extremes; geometry::detail::for_each_range(geometry, extremes); // Bounding left/right points // Second pass, now that extremes are found, assign all points // in either lower, either upper detail::assign_range < range_type, range_iterator, container_type, typename strategy::side::services::default_strategy<cs_tag>::type > assigner(extremes.left, extremes.right); geometry::detail::for_each_range(geometry, assigner); // Sort both collections, first on x(, then on y) detail::sort(assigner.lower_points); detail::sort(assigner.upper_points); //std::cout << boost::size(assigner.lower_points) << std::endl; //std::cout << boost::size(assigner.upper_points) << std::endl; // And decide which point should be in the final hull build_half_hull<-1>(assigner.lower_points, state.m_lower_hull, extremes.left, extremes.right); build_half_hull<1>(assigner.upper_points, state.m_upper_hull, extremes.left, extremes.right); }
static int kl_script_event_dequeue_wrap(lua_State* L) { kl_script_context_t sctx = (kl_script_context_t)lua_topointer(L, 1); kl_script_event_t event; if(kl_script_event_dequeue(sctx, &event) == KL_SUCCESS) { uint32_t context_type = kl_get_script_event_context_type(event.event.id); int ret = 3; lua_pushinteger(L, event.event.id); if(context_type == KL_SCRIPT_CONTEXT_TYPE_ASSIGNER) { kl_script_event_context_assigner_fn assigner = kl_get_script_event_context_assigner(event.event.id); ret = assigner(L, &event) + 1; } else { switch(context_type) { case 0: { lua_pushlightuserdata(L, event.event.context.as_ptr); break; } case LUA_TNUMBER: { lua_pushnumber(L, *((lua_Number*)event.event.context.as_ptr)); kl_heap_free(event.event.context.as_ptr); break; } case LUA_TSTRING: { lua_pushstring(L, event.event.context.as_ptr); kl_heap_free(event.event.context.as_ptr); break; } } lua_pushinteger(L, event.event.arg.as_uint32); } return ret; } lua_pushnil(L); return 1; }
int main(int argc, char* argv[]) { diy::mpi::environment env(argc, argv); diy::mpi::communicator world; diy::Master master(world, 1, -1, &create_block, // master will take ownership after read_blocks(), &destroy_block); // so it needs create and destroy functions diy::ContiguousAssigner assigner(world.size(), 0); //diy::RoundRobinAssigner assigner(world.size(), 0); // nblocks will be filled by read_blocks() diy::io::read_blocks("blocks.out", world, assigner, master, &load_block); master.foreach(&output); }
int main(int argc, char* argv[]) { diy::mpi::environment env(argc, argv); diy::mpi::communicator world; int nblocks = 4*world.size(); diy::FileStorage storage("./DIY.XXXXXX"); diy::Master master(world, -1, 2, &create_block, &destroy_block, &storage, &save_block, &load_block); srand(time(NULL)); //diy::ContiguousAssigner assigner(world.size(), nblocks); diy::RoundRobinAssigner assigner(world.size(), nblocks); for (int gid = 0; gid < nblocks; ++gid) if (assigner.rank(gid) == world.rank()) master.add(gid, new Block, new diy::Link); bool all_done = false; while (!all_done) { master.foreach(&flip_coin); master.exchange(); all_done = master.proxy(master.loaded_block()).read<bool>(); } if (world.rank() == 0) std::cout << "Total iterations: " << master.block<Block>(master.loaded_block())->count << std::endl; }
/*! * \param[in] data Data for the current frame. * \param[in] sel Selection element being evaluated. * \param[in] g Group for which \p sel should be evaluated. * \returns 0 on success, a non-zero error code on error. * * Finds the part of \p g for which the subexpression * has not yet been evaluated by comparing \p g to \p sel->u.cgrp. * If the part is not empty, the child expression is evaluated for this * part, and the results merged to the old values of the child. * The value of \p sel itself is undefined after the call. * * \todo * The call to gmx_ana_index_difference() can take quite a lot of unnecessary * time if the subexpression is evaluated either several times for the same * group or for completely distinct groups. * However, in the majority of cases, these situations occur when * _gmx_sel_evaluate_subexpr_staticeval() can be used, so this should not be a * major problem. */ void _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g) { gmx_ana_index_t gmiss; MempoolGroupReserver gmissreserver(data->mp); if (sel->u.cgrp.isize == 0) { { SelelemTemporaryValueAssigner assigner(sel->child, sel); sel->child->evaluate(data, sel->child, g); } /* We need to keep the name for the cgrp across the copy to avoid * problems if g has a name set. */ char *name = sel->u.cgrp.name; gmx_ana_index_copy(&sel->u.cgrp, g, false); sel->u.cgrp.name = name; gmiss.isize = 0; } else { gmissreserver.reserve(&gmiss, g->isize); gmx_ana_index_difference(&gmiss, g, &sel->u.cgrp); } if (gmiss.isize > 0) { MempoolSelelemReserver reserver(sel->child, gmiss.isize); /* Evaluate the missing values for the child */ sel->child->evaluate(data, sel->child, &gmiss); /* Merge the missing values to the existing ones. */ if (sel->v.type == GROUP_VALUE) { gmx_ana_index_merge(sel->v.u.g, sel->child->v.u.g, sel->v.u.g); } else { int i, j, k; i = sel->u.cgrp.isize - 1; j = gmiss.isize - 1; /* TODO: This switch is kind of ugly, but it may be difficult to * do this portably without C++ templates. */ switch (sel->v.type) { case INT_VALUE: for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--) { if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j])) { sel->v.u.i[k] = sel->v.u.i[j--]; } else { sel->v.u.i[k] = sel->child->v.u.i[i--]; } } break; case REAL_VALUE: for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--) { if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j])) { sel->v.u.r[k] = sel->v.u.r[j--]; } else { sel->v.u.r[k] = sel->child->v.u.r[i--]; } } break; case STR_VALUE: for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--) { if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j])) { sel->v.u.s[k] = sel->v.u.s[j--]; } else { sel->v.u.s[k] = sel->child->v.u.s[i--]; } } break; case POS_VALUE: /* TODO: Implement this */ GMX_THROW(gmx::NotImplementedError("position subexpressions not implemented properly")); case NO_VALUE: case GROUP_VALUE: GMX_THROW(gmx::InternalError("Invalid subexpression type")); } } gmx_ana_index_merge(&sel->u.cgrp, &sel->u.cgrp, &gmiss); } }
int main(int argc, char *argv[]) { int tot_blocks; // total number of blocks in the domain int mem_blocks; // max blocks in memory int dsize[3]; // domain grid size float jitter; // max amount to randomly displace particles float minvol, maxvol; // volume range, -1.0 = unused double times[TESS_MAX_TIMES]; // timing int wrap; // wraparound neighbors flag int walls; // apply walls to simulation (wrap must be off) char outfile[256]; // output file name int num_threads = 1; // threads diy can use // init MPI MPI_Comm comm = MPI_COMM_WORLD; MPI_Init(&argc, &argv); GetArgs(argc, argv, tot_blocks, mem_blocks, dsize, &jitter, &minvol, &maxvol, &wrap, &walls, outfile); // data extents typedef diy::ContinuousBounds Bounds; Bounds domain { 3 }; for(int i = 0; i < 3; i++) { domain.min[i] = 0; domain.max[i] = dsize[i] - 1.0; } // init diy diy::mpi::communicator world(comm); diy::FileStorage storage("./DIY.XXXXXX"); diy::Master master(world, num_threads, mem_blocks, &create_block, &destroy_block, &storage, &save_block, &load_block); diy::RoundRobinAssigner assigner(world.size(), tot_blocks); AddAndGenerate create(master, jitter); // decompose std::vector<int> my_gids; assigner.local_gids(world.rank(), my_gids); diy::RegularDecomposer<Bounds>::BoolVector wraps; diy::RegularDecomposer<Bounds>::BoolVector share_face; diy::RegularDecomposer<Bounds>::CoordinateVector ghosts; if (wrap) wraps.assign(3, true); diy::decompose(3, world.rank(), domain, assigner, create, share_face, wraps, ghosts); // tessellate quants_t quants; timing(times, -1, -1, world); timing(times, TOT_TIME, -1, world); tess(master, quants, times); // output tess_save(master, outfile, times); timing(times, -1, TOT_TIME, world); tess_stats(master, quants, times); MPI_Finalize(); return 0; }