1 #ifndef MPQC_ARRAY_PARALLEL_HPP
2 #define MPQC_ARRAY_PARALLEL_HPP
4 #include "mpqc/range.hpp"
5 #include "mpqc/array/forward.hpp"
6 #include "mpqc/array/thread.hpp"
7 #include "mpqc/utility/string.hpp"
14 std::vector<range> extents;
17 std::vector<range> subset(
const std::vector<range> &ranges)
const {
19 for (
int i = 0; i < ranges.size(); ++i) {
20 range r = (ranges[i] & this->extents[i]);
21 if (!r.size())
return std::vector<range>();
28 template<
typename T,
typename Driver>
37 const std::vector<size_t> &dims,
39 :
ArrayBase(name, dims), thread_comm_(comm)
41 initialize(ArrayBase::dims_, comm);
44 void initialize(
const std::vector<size_t> &dims,
const MPI::Comm &comm) {
47 size_t block = (dims.back() + np - 1)/np;
49 for (
int i = 0; i < dims.back(); i += block) {
52 int n = std::min(dims.back()-i, block);
54 BOOST_FOREACH (
size_t dim, dims) {
55 tile.extents.push_back(
range(0, dim));
57 tile.extents.back() = range(i, i+n);
59 tile.proc = (i/block)%np;
60 tile.local = (tile.proc == comm.rank());
64 std::string suffix =
".part" +
string_cast(comm.rank());
66 tile.data =
new Impl(this->name() + suffix, tile.extents);
68 catch (std::exception e) {
69 comm.cout << e.what() << std::endl;
73 comm.broadcast(tile.data, tile.proc);
75 throw std::runtime_error(
"failed to create parallel array segment");
77 tiles_.push_back(tile);
81 ~array_parallel_impl() {
82 BOOST_FOREACH (Tile t, tiles_) {
83 if (t.local)
delete t.data;
85 thread_comm_.comm().free();
94 void _put(
const std::vector<range> &r,
const void *buffer) {
95 _put(r, (
const T*)buffer);
98 void _get(
const std::vector<range> &r,
void *buffer)
const {
104 void _put(
const std::vector<range> &r,
const T *buffer) {
105 size_t total = size(r);
107 BOOST_FOREACH (
const auto &tile, tiles_) {
108 auto x = tile.subset(r);
117 thread_comm_.write(buffer + count, tile.data, x, tile.proc);
122 MPQC_ASSERT(total == count);
125 void _get(
const std::vector<range> &r, T *buffer)
const {
126 size_t total = size(r);
128 BOOST_FOREACH (
const auto &tile, tiles_) {
129 auto x = tile.subset(r);
139 thread_comm_.read(buffer + count, tile.data, x, tile.proc);
144 MPQC_ASSERT(total == count);
149 static size_t size(
const std::vector<range> &R) {
150 size_t size = R.empty() ? 0 : 1;
151 BOOST_FOREACH (range r, R) {
158 std::vector<Tile> tiles_;
159 array_thread_comm thread_comm_;