12 June 2020 at 11 h 30 min #16610AOParticipant
From the last update in the SofaPython3 (SP3) plugin, we now have two differents ways of setting a value from python to C++.
The first and old one is:
my_data.value = my_python_variable
The new one is:
with my_data.writeable() as foo: foo = my_python_variable
What’s the difference between both in terms of accessibility and what’s the benefit of the second one over the first.12 June 2020 at 12 h 08 min #16611Bruno MarquesParticipant
Hi @AlbanOdot ,
Here’s the short answer:
- how to use writeable():
with self.CFF.forces.writeable() as cff: cff[:] = linear_forces_amplitude * layer
- when should I use which:
in your case
self.CFF.forces.value = linear_force_amplitude * Layeris as efficient as the writeable version
The long answer now:
Your first question raises some technical discussions regarding python binding optimizations, I’ll do my best to explain:
When you’re editing a datafield in SOFA, there’s a mechanism that guarantees a thread-safe access by locking / unlocking the access to the data when trying to edit. A call to
setValue()for instance does 3 things:
- lock the data (like a mutex)
- edit the data
- unlock the data to be accessed by other calling points
In the case of the
setValue()function, this is “invisible” to the user as everything is performed within the function. But when the data is a large vector of values for instance, and that you want to run a set of operations on those values, from the c++ we use beginEdit / endEdit (the locking / unlocking mechanism used within setValue(), that you might have seen in the code of SOFA components already.
When it comes to SofaPython3, we want to expose c++ buffers in Python by wrapping it in a numpy array. This is what the
writeable()function does. But we are still required to use the locking / unlocking mechanism. So if we simply expose the buffer directly using let’s set a
getValue()function returning a writeable buffer, beginEdit() will be called to retreive the value within the getValue() binding function, then the buffer will be returned to python. Now we are inside the python code, with a writeable buffer in our hands, but no clear way on how to “release” the data. We could simply implement an
endEdit()method, but who will think of calling it? This is a huge problem in terms of error management.
To circumvent this issue, developers came up with a concept called “RAII” (resource acquisition is initialization). The idea behind RAII is to guarantee that whenever a resource is accessed (here the value of a datafield), its automatic release is guaranteed once were done with it. To do so, the releasing of the resource is attached to the lifetime of the scope in which the resource is being used (which must of course be as short as possible). In the case of SofaPython3, we do this using a ContextManager (with … as xxx:)
The usage of ContextManagers lets the user perform as many operations on your datafield as you want, while only calling beginEdit only once when entering the context (scope), and calling endEdit only once when leaving it.
This is particularily important in python bindings because if you were to call setValue() XXX times to set all the values of a vector datafield for instance, you would ping-pong back and forth between python and c++ through the bindings, each time copying values, which obviously, is very costly and suboptimal.
So in conclusion:
- If you want to perform a single operation on a data : Just use
myData.value = whateverValue, because anyway, there’s only 1 instruction to execute, so 1 single round-trip through the bindings.
- If you’re planning on performing a set of operations on a datafield (for instance running an instruction on each element of a vector field through a for loop…): use a ContextManager: It will significantly limit the number of calls to python bindings and the number of copies of your data, while letting you perform as many operations as you want within the scope of that ContextManager
Here, I hope those explanations are clear enough 😉12 June 2020 at 16 h 25 min #16616AOParticipant
Thanks, it’s very clear now 🙂
- You must be logged in to reply to this topic.