votca 2026-dev
Loading...
Searching...
No Matches
gridboxaccumulator.h
Go to the documentation of this file.
1/*
2 * Copyright 2009-2026 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20#pragma once
21#ifndef VOTCA_XTP_GRIDBOXACCUMULATOR_H
22#define VOTCA_XTP_GRIDBOXACCUMULATOR_H
23
24// Standard includes
25#include <cstddef>
26#include <utility>
27#include <vector>
28
29#ifdef _OPENMP
30#include <omp.h>
31#endif
32
33// Local VOTCA includes
34#include "votca/xtp/eigen.h"
35#include "votca/xtp/gridbox.h"
36
37namespace votca {
38namespace xtp {
39
57 public:
60 explicit GridBoxAccumulator(std::vector<Eigen::MatrixXd*> targets,
61 double budget_bytes = 2.0e9)
62 : targets_(std::move(targets)) {
63 const Index n = Index(targets_.size());
64 const Index nthreads = OPENMP::getMaxThreads();
65 double bytes = 0.0;
66 for (const Eigen::MatrixXd* m : targets_) {
67 bytes += double(m->size()) * double(sizeof(double));
68 }
70 nthreads > 1 && double(nthreads - 1) * bytes <= budget_bytes;
71 if (thread_local_) {
72 // thread 0 writes into the targets themselves; the others get copies on
73 // first use
74 copies_.resize(std::size_t(nthreads));
75 }
76#ifdef _OPENMP
77 if (!thread_local_ && nthreads > 1) {
78 locks_.resize(std::size_t(n));
79 for (omp_lock_t& l : locks_) {
80 omp_init_lock(&l);
81 }
82 }
83#endif
84 (void)n;
85 }
86
88#ifdef _OPENMP
89 for (omp_lock_t& l : locks_) {
90 omp_destroy_lock(&l);
91 }
92#endif
93 }
96
97 bool UsesThreadLocalCopies() const { return thread_local_; }
98
101 void Add(const GridBox& box,
102 const std::vector<const Eigen::MatrixXd*>& small) {
103 const Index n = Index(targets_.size());
104 const Index tid = OPENMP::getThreadId();
105 if (thread_local_) {
106 if (tid == 0) {
107 for (Index k = 0; k < n; ++k) {
108 if (small[std::size_t(k)]->size() > 0) {
109 box.AddtoBigMatrix(*targets_[std::size_t(k)],
110 *small[std::size_t(k)]);
111 }
112 }
113 return;
114 }
115 if (tid >= Index(copies_.size())) { // more threads than at construction
116#pragma omp critical(votca_xtp_gridboxaccumulator)
117 {
118 for (Index k = 0; k < n; ++k) {
119 if (small[std::size_t(k)]->size() > 0) {
120 box.AddtoBigMatrix(*targets_[std::size_t(k)],
121 *small[std::size_t(k)]);
122 }
123 }
124 }
125 return;
126 }
127 std::vector<Eigen::MatrixXd>& mine = copies_[std::size_t(tid)];
128 if (mine.empty()) {
129 mine.reserve(std::size_t(n));
130 for (const Eigen::MatrixXd* m : targets_) {
131 mine.push_back(Eigen::MatrixXd::Zero(m->rows(), m->cols()));
132 }
133 }
134 for (Index k = 0; k < n; ++k) {
135 if (small[std::size_t(k)]->size() > 0) {
136 box.AddtoBigMatrix(mine[std::size_t(k)], *small[std::size_t(k)]);
137 }
138 }
139 return;
140 }
141#ifdef _OPENMP
142 if (!locks_.empty()) {
143 for (Index j = 0; j < n; ++j) {
144 const Index k = (j + tid) % n;
145 if (small[std::size_t(k)]->size() == 0) {
146 continue;
147 }
148 omp_set_lock(&locks_[std::size_t(k)]);
149 box.AddtoBigMatrix(*targets_[std::size_t(k)], *small[std::size_t(k)]);
150 omp_unset_lock(&locks_[std::size_t(k)]);
151 }
152 return;
153 }
154#endif
155 for (Index k = 0; k < n; ++k) {
156 if (small[std::size_t(k)]->size() > 0) {
157 box.AddtoBigMatrix(*targets_[std::size_t(k)], *small[std::size_t(k)]);
158 }
159 }
160 }
161
163 void Finish() {
164 if (!thread_local_) {
165 return;
166 }
167 const Index n = Index(targets_.size());
168#pragma omp parallel for schedule(static)
169 for (Index k = 0; k < n; ++k) {
170 for (const std::vector<Eigen::MatrixXd>& c : copies_) {
171 if (!c.empty()) {
172 *targets_[std::size_t(k)] += c[std::size_t(k)];
173 }
174 }
175 }
176 copies_.clear();
177 }
178
179 private:
180 std::vector<Eigen::MatrixXd*> targets_;
181 bool thread_local_ = false;
182 std::vector<std::vector<Eigen::MatrixXd>> copies_;
183#ifdef _OPENMP
184 std::vector<omp_lock_t> locks_;
185#endif
186};
187
188} // namespace xtp
189} // namespace votca
190
191#endif // VOTCA_XTP_GRIDBOXACCUMULATOR_H
GridBoxAccumulator & operator=(const GridBoxAccumulator &)=delete
void Finish()
sums the thread-local copies into the targets (call outside the loop)
std::vector< std::vector< Eigen::MatrixXd > > copies_
std::vector< Eigen::MatrixXd * > targets_
GridBoxAccumulator(std::vector< Eigen::MatrixXd * > targets, double budget_bytes=2.0e9)
void Add(const GridBox &box, const std::vector< const Eigen::MatrixXd * > &small)
GridBoxAccumulator(const GridBoxAccumulator &)=delete
void AddtoBigMatrix(Eigen::MatrixXd &bigmatrix, const Eigen::MatrixXd &smallmatrix) const
Definition gridbox.cc:84
STL namespace.
Index getMaxThreads()
Definition eigen.h:145
Index getThreadId()
Definition eigen.h:160
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26