Skip to content

Commit 304b64e

Browse files
alxbilgerhugtalbot
andauthored
Binding to setup task scheduler (nb threads) (#366)
* Binding to setup task scheduler (nb threads) * Update examples/taskScheduler.py Co-authored-by: Hugo <hugo.talbot@sofa-framework.org> --------- Co-authored-by: Hugo <hugo.talbot@sofa-framework.org>
1 parent dd5a12c commit 304b64e

6 files changed

Lines changed: 202 additions & 0 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/******************************************************************************
2+
* SofaPython3 plugin *
3+
* (c) 2021 CNRS, University of Lille, INRIA *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: contact@sofa-framework.org *
19+
******************************************************************************/
20+
21+
#include <SofaPython3/Sofa/Core/Binding_TaskScheduler.h>
22+
#include <sofa/simulation/MainTaskSchedulerFactory.h>
23+
#include <sofa/simulation/TaskScheduler.h>
24+
#include <SofaPython3/Sofa/Core/Binding_TaskScheduler_doc.h>
25+
26+
27+
/// Makes an alias for the pybind11 namespace to increase readability.
28+
namespace py { using namespace pybind11; }
29+
30+
namespace sofapython3
31+
{
32+
py::module moduleAddTaskScheduler(py::module& m)
33+
{
34+
py::module taskSchedulerModule = m.def_submodule("TaskScheduler");
35+
36+
taskSchedulerModule.doc() = R"doc(
37+
TaskScheduler
38+
-----------------------
39+
40+
Configuration of the main task scheduler.
41+
)doc";
42+
43+
44+
taskSchedulerModule.def("init", [](const unsigned int nbThreads)
45+
{
46+
auto* const taskScheduler = sofa::simulation::MainTaskSchedulerFactory::createInRegistry();
47+
assert(taskScheduler);
48+
taskScheduler->init(nbThreads);
49+
}, sofapython3::doc::taskscheduler::init);
50+
51+
taskSchedulerModule.def("getThreadCount", []()
52+
{
53+
const auto* const taskScheduler = sofa::simulation::MainTaskSchedulerFactory::createInRegistry();
54+
assert(taskScheduler);
55+
return taskScheduler->getThreadCount();
56+
}, sofapython3::doc::taskscheduler::getThreadCount);
57+
58+
taskSchedulerModule.def("stop", []()
59+
{
60+
auto* const taskScheduler = sofa::simulation::MainTaskSchedulerFactory::createInRegistry();
61+
assert(taskScheduler);
62+
return taskScheduler->stop();
63+
});
64+
65+
taskSchedulerModule.def("GetHardwareThreadsCount", []()
66+
{
67+
return sofa::simulation::TaskScheduler::GetHardwareThreadsCount();
68+
}, sofapython3::doc::taskscheduler::GetHardwareThreadsCount);
69+
70+
return taskSchedulerModule;
71+
}
72+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/******************************************************************************
2+
* SofaPython3 plugin *
3+
* (c) 2021 CNRS, University of Lille, INRIA *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: contact@sofa-framework.org *
19+
******************************************************************************/
20+
21+
#pragma once
22+
23+
#include <pybind11/pybind11.h>
24+
25+
namespace sofapython3 {
26+
27+
pybind11::module moduleAddTaskScheduler(pybind11::module& m);
28+
29+
} /// namespace sofapython3
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/******************************************************************************
2+
* SofaPython3 plugin *
3+
* (c) 2021 CNRS, University of Lille, INRIA *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: contact@sofa-framework.org *
19+
******************************************************************************/
20+
21+
#pragma once
22+
23+
namespace sofapython3::doc::taskscheduler
24+
{
25+
26+
static auto init =
27+
R"(
28+
Initialize the main task scheduler with a number of threads.
29+
)";
30+
31+
static auto getThreadCount =
32+
R"(
33+
Returns the number of threads used by the main task scheduler.
34+
)";
35+
36+
static auto GetHardwareThreadsCount =
37+
R"(
38+
Assuming 2 concurrent threads by CPU core, return the number of CPU cores on the system
39+
)";
40+
}

bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ set(HEADER_FILES
4545
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseCamera_doc.h
4646
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Topology.h
4747
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseMeshTopology.h
48+
${CMAKE_CURRENT_SOURCE_DIR}/Binding_TaskScheduler.h
49+
${CMAKE_CURRENT_SOURCE_DIR}/Binding_TaskScheduler_doc.h
4850
)
4951

5052
set(SOURCE_FILES
@@ -75,6 +77,7 @@ set(SOURCE_FILES
7577
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseLink.cpp
7678
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Topology.cpp
7779
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseMeshTopology.cpp
80+
${CMAKE_CURRENT_SOURCE_DIR}/Binding_TaskScheduler.cpp
7881
)
7982

8083
if (NOT TARGET SofaPython3::Plugin)

bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ using sofa::helper::logging::Message;
4444
#include <SofaPython3/Sofa/Core/Binding_PythonScriptEvent.h>
4545
#include <SofaPython3/Sofa/Core/Binding_Topology.h>
4646
#include <SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h>
47+
#include <SofaPython3/Sofa/Core/Binding_TaskScheduler.h>
4748

4849
#include <SofaPython3/Sofa/Core/Data/Binding_DataString.h>
4950
#include <SofaPython3/Sofa/Core/Data/Binding_DataLink.h>
@@ -128,6 +129,7 @@ PYBIND11_MODULE(Core, core)
128129
moduleAddTopology(core);
129130
moduleAddBaseMeshTopology(core);
130131
moduleAddPointSetTopologyModifier(core);
132+
moduleAddTaskScheduler(core);
131133
}
132134

133135
} ///namespace sofapython3

examples/taskScheduler.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import Sofa
2+
from Sofa.Core import TaskScheduler
3+
import time
4+
5+
def createScene(root):
6+
root.dt = 0.01
7+
8+
root.addObject("RequiredPlugin", pluginName=[
9+
"MultiThreading",
10+
"Sofa.Component.Constraint.Projective",
11+
"Sofa.Component.Engine.Select",
12+
"Sofa.Component.LinearSolver.Iterative",
13+
"Sofa.Component.Mass",
14+
"Sofa.Component.ODESolver.Backward",
15+
"Sofa.Component.StateContainer",
16+
"Sofa.Component.Topology.Container.Grid",
17+
"Sofa.Component.Visual",
18+
"Sofa.Component.Topology.Container.Dynamic",
19+
])
20+
root.addObject('VisualStyle', displayFlags="showForceFields")
21+
root.addObject('DefaultAnimationLoop')
22+
root.addObject('EulerImplicitSolver', rayleighStiffness=0.1, rayleighMass=0.1)
23+
root.addObject('CGLinearSolver', iterations=25, tolerance=1.0e-9, threshold=1.0e-9)
24+
root.addObject('MechanicalObject', template="Vec3")
25+
root.addObject('UniformMass', vertexMass=1)
26+
root.addObject('RegularGridTopology', nx=8, ny=8, nz=40, xmin=-1.5, xmax=1.5, ymin=-1.5, ymax=1.5, zmin=0, zmax=19)
27+
root.addObject('BoxROI', box=[-1.5, -1.5, 0, 1.5, 1.5, 0.0001], name="box")
28+
root.addObject('FixedConstraint', indices="@box.indices")
29+
root.addObject('ParallelHexahedronFEMForceField', youngModulus=400000, poissonRatio=0.4, method="large", updateStiffnessMatrix=False)
30+
31+
32+
# When not using runSofa, this main function will be called python
33+
def main():
34+
root = Sofa.Core.Node("root")
35+
createScene(root)
36+
Sofa.Simulation.init(root)
37+
38+
for nb_threads in range(1, TaskScheduler.GetHardwareThreadsCount() + 1):
39+
print(f'Number of threads #{nb_threads}')
40+
Sofa.Simulation.reset(root)
41+
TaskScheduler.init(nb_threads)
42+
43+
start = time.time()
44+
for iteration in range(500):
45+
Sofa.Simulation.animate(root, root.dt.value)
46+
end = time.time()
47+
print("500 iterations computed in " + str(end - start) + " seconds")
48+
49+
print("Stopping...")
50+
TaskScheduler.stop()
51+
print("Stopped")
52+
53+
54+
55+
if __name__ == '__main__':
56+
main()

0 commit comments

Comments
 (0)