Skip to content

Commit

Permalink
Binding to setup task scheduler (nb threads) (#366)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
alxbilger and hugtalbot authored Aug 23, 2023
1 parent dd5a12c commit 304b64e
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 0 deletions.
72 changes: 72 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_TaskScheduler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/******************************************************************************
* SofaPython3 plugin *
* (c) 2021 CNRS, University of Lille, INRIA *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: contact@sofa-framework.org *
******************************************************************************/

#include <SofaPython3/Sofa/Core/Binding_TaskScheduler.h>
#include <sofa/simulation/MainTaskSchedulerFactory.h>
#include <sofa/simulation/TaskScheduler.h>
#include <SofaPython3/Sofa/Core/Binding_TaskScheduler_doc.h>


/// Makes an alias for the pybind11 namespace to increase readability.
namespace py { using namespace pybind11; }

namespace sofapython3
{
py::module moduleAddTaskScheduler(py::module& m)
{
py::module taskSchedulerModule = m.def_submodule("TaskScheduler");

taskSchedulerModule.doc() = R"doc(
TaskScheduler
-----------------------
Configuration of the main task scheduler.
)doc";


taskSchedulerModule.def("init", [](const unsigned int nbThreads)
{
auto* const taskScheduler = sofa::simulation::MainTaskSchedulerFactory::createInRegistry();
assert(taskScheduler);
taskScheduler->init(nbThreads);
}, sofapython3::doc::taskscheduler::init);

taskSchedulerModule.def("getThreadCount", []()
{
const auto* const taskScheduler = sofa::simulation::MainTaskSchedulerFactory::createInRegistry();
assert(taskScheduler);
return taskScheduler->getThreadCount();
}, sofapython3::doc::taskscheduler::getThreadCount);

taskSchedulerModule.def("stop", []()
{
auto* const taskScheduler = sofa::simulation::MainTaskSchedulerFactory::createInRegistry();
assert(taskScheduler);
return taskScheduler->stop();
});

taskSchedulerModule.def("GetHardwareThreadsCount", []()
{
return sofa::simulation::TaskScheduler::GetHardwareThreadsCount();
}, sofapython3::doc::taskscheduler::GetHardwareThreadsCount);

return taskSchedulerModule;
}
}
29 changes: 29 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_TaskScheduler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/******************************************************************************
* SofaPython3 plugin *
* (c) 2021 CNRS, University of Lille, INRIA *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: contact@sofa-framework.org *
******************************************************************************/

#pragma once

#include <pybind11/pybind11.h>

namespace sofapython3 {

pybind11::module moduleAddTaskScheduler(pybind11::module& m);

} /// namespace sofapython3
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/******************************************************************************
* SofaPython3 plugin *
* (c) 2021 CNRS, University of Lille, INRIA *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: contact@sofa-framework.org *
******************************************************************************/

#pragma once

namespace sofapython3::doc::taskscheduler
{

static auto init =
R"(
Initialize the main task scheduler with a number of threads.
)";

static auto getThreadCount =
R"(
Returns the number of threads used by the main task scheduler.
)";

static auto GetHardwareThreadsCount =
R"(
Assuming 2 concurrent threads by CPU core, return the number of CPU cores on the system
)";
}
3 changes: 3 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseCamera_doc.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Topology.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseMeshTopology.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_TaskScheduler.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_TaskScheduler_doc.h
)

set(SOURCE_FILES
Expand Down Expand Up @@ -75,6 +77,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseLink.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Topology.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseMeshTopology.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_TaskScheduler.cpp
)

if (NOT TARGET SofaPython3::Plugin)
Expand Down
2 changes: 2 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ using sofa::helper::logging::Message;
#include <SofaPython3/Sofa/Core/Binding_PythonScriptEvent.h>
#include <SofaPython3/Sofa/Core/Binding_Topology.h>
#include <SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h>
#include <SofaPython3/Sofa/Core/Binding_TaskScheduler.h>

#include <SofaPython3/Sofa/Core/Data/Binding_DataString.h>
#include <SofaPython3/Sofa/Core/Data/Binding_DataLink.h>
Expand Down Expand Up @@ -128,6 +129,7 @@ PYBIND11_MODULE(Core, core)
moduleAddTopology(core);
moduleAddBaseMeshTopology(core);
moduleAddPointSetTopologyModifier(core);
moduleAddTaskScheduler(core);
}

} ///namespace sofapython3
56 changes: 56 additions & 0 deletions examples/taskScheduler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Sofa
from Sofa.Core import TaskScheduler
import time

def createScene(root):
root.dt = 0.01

root.addObject("RequiredPlugin", pluginName=[
"MultiThreading",
"Sofa.Component.Constraint.Projective",
"Sofa.Component.Engine.Select",
"Sofa.Component.LinearSolver.Iterative",
"Sofa.Component.Mass",
"Sofa.Component.ODESolver.Backward",
"Sofa.Component.StateContainer",
"Sofa.Component.Topology.Container.Grid",
"Sofa.Component.Visual",
"Sofa.Component.Topology.Container.Dynamic",
])
root.addObject('VisualStyle', displayFlags="showForceFields")
root.addObject('DefaultAnimationLoop')
root.addObject('EulerImplicitSolver', rayleighStiffness=0.1, rayleighMass=0.1)
root.addObject('CGLinearSolver', iterations=25, tolerance=1.0e-9, threshold=1.0e-9)
root.addObject('MechanicalObject', template="Vec3")
root.addObject('UniformMass', vertexMass=1)
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)
root.addObject('BoxROI', box=[-1.5, -1.5, 0, 1.5, 1.5, 0.0001], name="box")
root.addObject('FixedConstraint', indices="@box.indices")
root.addObject('ParallelHexahedronFEMForceField', youngModulus=400000, poissonRatio=0.4, method="large", updateStiffnessMatrix=False)


# When not using runSofa, this main function will be called python
def main():
root = Sofa.Core.Node("root")
createScene(root)
Sofa.Simulation.init(root)

for nb_threads in range(1, TaskScheduler.GetHardwareThreadsCount() + 1):
print(f'Number of threads #{nb_threads}')
Sofa.Simulation.reset(root)
TaskScheduler.init(nb_threads)

start = time.time()
for iteration in range(500):
Sofa.Simulation.animate(root, root.dt.value)
end = time.time()
print("500 iterations computed in " + str(end - start) + " seconds")

print("Stopping...")
TaskScheduler.stop()
print("Stopped")



if __name__ == '__main__':
main()

0 comments on commit 304b64e

Please sign in to comment.