File: ParallelEngine.cpp

package info (click to toggle)
yade 2026.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 34,448 kB
  • sloc: cpp: 97,645; python: 52,173; sh: 677; makefile: 162
file content (84 lines) | stat: -rw-r--r-- 2,414 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <pkg/common/ParallelEngine.hpp>

#ifdef YADE_OPENMP
#include <omp.h>
#endif

namespace yade { // Cannot have #include directive inside.

YADE_PLUGIN((ParallelEngine));

//! ParallelEngine's pseudo-ctor (factory), taking nested lists of slave engines (might be moved to real ctor perhaps)
shared_ptr<ParallelEngine> ParallelEngine_ctor_list(const boost::python::list& slaves)
{
	shared_ptr<ParallelEngine> instance(new ParallelEngine);
	instance->slaves_set(slaves);
	return instance;
}

void ParallelEngine::action()
{
	// openMP warns if the iteration variable is unsigned...
	const int  size               = (int)slaves.size();
	const bool TimingInfo_enabled = TimingInfo::enabled;
#ifdef YADE_OPENMP
	//nested parallel regions are disabled by default on some platforms, we enable them since some of the subengine may be also parallel
	omp_set_nested(1);
#pragma omp parallel for num_threads(ompThreads)

#endif
	for (int i = 0; i < size; i++) {
		TimingInfo::delta last = TimingInfo::getNow();
		// run every slave group sequentially
		FOREACH(const shared_ptr<Engine>& e, slaves[i])
		{
			e->scene = scene;
			if (!e->dead && e->isActivated()) {
				e->action();
				if (TimingInfo_enabled) {
					TimingInfo::delta now = TimingInfo::getNow();
					e->timingInfo.nsec += now - last;
					e->timingInfo.nExec += 1;
					last = now;
				}
			}
		}
	}
}

void ParallelEngine::slaves_set(const boost::python::list& slaves2)
{
	int len = boost::python::len(slaves2);
	slaves.clear();
	for (int i = 0; i < len; i++) {
		boost::python::extract<std::vector<shared_ptr<Engine>>> serialGroup(slaves2[i]);
		if (serialGroup.check()) {
			slaves.push_back(serialGroup());
			continue;
		}
		boost::python::extract<shared_ptr<Engine>> serialAlone(slaves2[i]);
		if (serialAlone.check()) {
			vector<shared_ptr<Engine>> aloneWrap;
			aloneWrap.push_back(serialAlone());
			slaves.push_back(aloneWrap);
			continue;
		}
		PyErr_SetString(
		        PyExc_TypeError, "List elements must be either\n (a) sequences of engines to be executed one after another\n(b) alone engines.");
		boost::python::throw_error_already_set();
	}
}

boost::python::list ParallelEngine::slaves_get()
{
	boost::python::list ret;
	FOREACH(vector<shared_ptr<Engine>> & grp, slaves)
	{
		if (grp.size() == 1) ret.append(boost::python::object(grp[0]));
		else
			ret.append(boost::python::object(grp));
	}
	return ret;
}

} // namespace yade