Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | |||
671 | werner | 2 | /******************************************************************************************** |
3 | ** iLand - an individual based forest landscape and disturbance model |
||
4 | ** http://iland.boku.ac.at |
||
5 | ** Copyright (C) 2009- Werner Rammer, Rupert Seidl |
||
6 | ** |
||
7 | ** This program is free software: you can redistribute it and/or modify |
||
8 | ** it under the terms of the GNU General Public License as published by |
||
9 | ** the Free Software Foundation, either version 3 of the License, or |
||
10 | ** (at your option) any later version. |
||
11 | ** |
||
12 | ** This program is distributed in the hope that it will be useful, |
||
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
15 | ** GNU General Public License for more details. |
||
16 | ** |
||
17 | ** You should have received a copy of the GNU General Public License |
||
18 | ** along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
19 | ********************************************************************************************/ |
||
20 | |||
123 | Werner | 21 | #ifndef THREADRUNNER_H |
22 | #define THREADRUNNER_H |
||
440 | werner | 23 | #include <QList> |
878 | werner | 24 | #include <QtConcurrent/QtConcurrent> |
187 | iland | 25 | class ResourceUnit; |
475 | werner | 26 | class Species; |
123 | Werner | 27 | class ThreadRunner |
28 | { |
||
29 | public: |
||
30 | ThreadRunner(); |
||
475 | werner | 31 | ThreadRunner(const QList<Species*> &speciesList) { setup(speciesList);} |
32 | |||
33 | void setup(const QList<ResourceUnit*> &resourceUnitList); |
||
34 | void setup(const QList<Species*> &speciesList) { mSpeciesMap = speciesList; } |
||
35 | // access |
||
145 | Werner | 36 | bool multithreading() const { return mMultithreaded; } |
123 | Werner | 37 | void setMultithreading(const bool do_multithreading) { mMultithreaded = do_multithreading; } |
475 | werner | 38 | void print(); ///< print useful debug messages |
39 | // actions |
||
1157 | werner | 40 | void run( void (*funcptr)(ResourceUnit*), const bool forceSingleThreaded=false ); ///< execute 'funcptr' for all resource units in parallel |
41 | void run( void (*funcptr)(Species*), const bool forceSingleThreaded=false ); ///< execute 'funcptr' for set of species in parallel |
||
42 | // run over elements of a vector of type T |
||
878 | werner | 43 | template<class T> void run(T* (*funcptr)(T*), const QVector<T*> &container, const bool forceSingleThreaded=false) const; |
1157 | werner | 44 | // run over chunks of a larger array (or grid) |
45 | template<class T> void runGrid(void (*funcptr)(T*, T*), T* begin, T* end, const bool forceSingleThreaded=false, int minsize=10000, int maxchunks=10000) const; |
||
123 | Werner | 46 | private: |
187 | iland | 47 | QList<ResourceUnit*> mMap1, mMap2; |
475 | werner | 48 | QList<Species*> mSpeciesMap; |
49 | static bool mMultithreaded; |
||
123 | Werner | 50 | }; |
51 | |||
1157 | werner | 52 | template<class T> |
53 | void ThreadRunner::runGrid(void (*funcptr)(T *, T*), T *begin, T *end, const bool forceSingleThreaded, int minsize, int maxchunks) const |
||
54 | { |
||
55 | int length = end - begin; // # of elements |
||
56 | if (mMultithreaded && length>minsize*3 && forceSingleThreaded==false) { |
||
57 | // create multiple calls |
||
58 | int chunksize = minsize; |
||
59 | if (length > chunksize*maxchunks) { |
||
60 | chunksize = length / maxchunks; |
||
61 | } |
||
62 | // execute operations |
||
63 | T* p = begin; |
||
64 | while (p<end) { |
||
65 | T* pend = std::min(p+chunksize, end); |
||
66 | QtConcurrent::run(funcptr, p, pend); |
||
67 | p = pend; |
||
68 | } |
||
69 | } else { |
||
70 | // run all in one big function call |
||
71 | (*funcptr)(begin, end); |
||
72 | } |
||
73 | } |
||
74 | |||
878 | werner | 75 | // multirunning function |
76 | template<class T> |
||
77 | void ThreadRunner::run(T *(*funcptr)(T *), const QVector<T *> &container, const bool forceSingleThreaded) const |
||
78 | { |
||
79 | if (mMultithreaded && container.count() > 3 && forceSingleThreaded==false) { |
||
80 | // execute using QtConcurrent for larger amounts of elements |
||
81 | QtConcurrent::blockingMap(container,funcptr); |
||
82 | } else { |
||
83 | // execute serialized in main thread |
||
84 | T *element; |
||
85 | foreach(element, container) |
||
86 | (*funcptr)(element); |
||
87 | } |
||
88 | |||
89 | } |
||
90 | |||
123 | Werner | 91 | #endif // THREADRUNNER_H |