template<typename T, typename Op> void reduce_impl(const alps::mpi::communicator & comm, T const & in_values, T & out_values, Op op, int root, boost::false_type, boost::false_type) { using alps::hdf5::is_vectorizable; if (is_vectorizable(in_values)) { using alps::hdf5::get_extent; typedef typename alps::hdf5::scalar_type<T>::type scalar_type; std::vector<std::size_t> extent(get_extent(in_values)); std::vector<scalar_type> in_buffer(std::accumulate(extent.begin(), extent.end(), 1, std::multiplies<std::size_t>())); std::vector<scalar_type> out_buffer(in_buffer); using detail::copy_to_buffer; copy_to_buffer(in_values, in_buffer, 0, typename hdf5::is_content_continuous<T>::type()); // using boost::mpi::reduce; // reduce(comm, &in_buffer.front(), in_buffer.size(), &out_buffer.front(), op, root); using alps::mpi::get_mpi_datatype; MPI_Reduce(&in_buffer.front(), &out_buffer.front(), in_buffer.size(), get_mpi_datatype(scalar_type()), alps::mpi::is_mpi_op<Op, scalar_type>::op(), root, comm); using alps::hdf5::set_extent; set_extent(out_values, std::vector<std::size_t>(extent.begin(), extent.end())); using detail::copy_from_buffer; copy_from_buffer(out_values, out_buffer, 0, typename hdf5::is_content_continuous<T>::type()); } else throw std::logic_error("No alps::mpi::reduce available for this type " + std::string(typeid(T).name()) + ALPS_STACKTRACE); }
/** @brief Copy a buffer into a container value. The container value is of type T which ultimately holds values of a scalar type S (T can, e.g., be a container of containers of containers... of S). The values are copied from `buffer[offset]` to `values`. @param values: container to copy to; @param buffer: vector to copy from, starting from offset; @param offset: position in the buffer to copy from; @returns the new offset pointing right after the last used position in the buffer. @warning FIXME (design bug?) Although the container `values` is declared as a const reference, its content is modified by this function. */ template<typename T, typename S> std::size_t copy_from_buffer(T const & values, std::vector<S> & buffer, std::size_t offset, boost::false_type) { for(typename T::const_iterator it = values.begin(); it != values.end(); ++it) offset = copy_from_buffer(*it, buffer, offset, typename hdf5::is_continuous<typename T::value_type>::type()); return offset; }