Is using evaluate contextmanager safe?

19 views
Skip to first unread message

Paul Royik

unread,
Aug 1, 2020, 1:40:01 PM8/1/20
to sympy
In sympy.core.parameters it is written that "WARNING! Although the global parameters are thread-local, SymPy's cache is not by now. This may lead to undesired result in multi-threading operations.
But in code I see

def __setattr__(self, name, value):
if getattr(self, name) != value:
clear_cache()
return super().__setattr__(name, value)

So, does this workaround help to use this feature safely?

Oscar Benjamin

unread,
Aug 1, 2020, 3:40:19 PM8/1/20
to sympy
It possibly helps but it isn't really thread-safe. The problem is that
there isn't a single cache, there are many little caches and clearing
them all can take some time and is not atomic. If you have two threads
using the same cache but with different settings for the global
parameters then one thread might insert items into the cache while
another is clearing the cache. By the time clear_cache finishes the
cache might not actually be empty.

To make the cache properly thread-safe in a situation where threads
can independently alter the global parameters there needs to be a
separate cache for each thread.

Personally I think that the ultimate fix is the elimination of all
global parameters. That's not easy but it's what we should aim for.

--
Oscar

Paul Royik

unread,
Aug 2, 2020, 1:32:03 AM8/2/20
to sympy
Do you mean that now it is not safe to use evaluate=True in one thread and evaluate=False in another?

Oscar Benjamin

unread,
Aug 2, 2020, 5:00:47 AM8/2/20
to sympy
On Sun, 2 Aug 2020 at 06:32, Paul Royik <distan...@gmail.com> wrote:
>
> Do you mean that now it is not safe to use evaluate=True in one thread and evaluate=False in another?

It is always fine to use evaluate=True/False. The problem is with
using the global evaluate flag:

In [7]: with evaluate(False):
...: a = x + x
...:

In [8]: a
Out[8]: x + x

The global flag implicitly changes the behaviour of low-level routines
so if a higher-level result is cached with one setting of the global
flag then it might not be valid for another setting of the flag. The
cache is cleared when changing the flag but that is not thread-safe if
two threads are running at the same time.

It is fine to use evaluate=True/False. It is fine (as far as I know)
to use threads without changing any of the global flags. I think it's
also fine to change the global flags once before starting any threads.

What is not fine is having multiple threads running simultaneously and
changing the global flags while those threads are running.


Oscar

Paul Royik

unread,
Aug 2, 2020, 3:23:05 PM8/2/20
to sympy
Got it. Thanks.
Reply all
Reply to author
Forward
0 new messages