On Sun, Jun 13, 2010 at 05:26:16PM +0200, Jens Vollinga wrote:
I'm afraid you've missed the point. I wanted to explain that one of the essential mechanisms used by GiNaC (memory management) is not thread safe, therefore all setups (except using GiNaC from one thread) are unsafe.
this I don't believe yet. Maybe I am wrong, but the setup as he described it has no (and will not have any) sharing of subexpressions between threads.
I'm afraid tracking shared subexpressions is somewhat nontrivial. Consider the following example: ex a = pow(x1 + x2 + x3, 2); ex b = pow(x1 - x2 - x3, 3); ex e[2]; e[0] = a*b; e[1] = (a*b).diff(x1); Expressions e[0] and e[1] share a and b (that's just a funny implementation detail). Suppose thread A operates on e[0] and thread B operates on e[1]: // thread A e[0] = e[0].expand(); // no references to a and b any more // thread B e[1] = e[1].diff(x2); // a*b'' + 2*a'*b' + a''*b, one more reference to a and b Thread A has no references to a and b after expand() completes its job, so it will try to decrement their refcount. On the other hand, thread B will try to increment refcounts of a and b. That's a disaster, since nothing protects refcount from concurrent modification. [It's easy to find out shared subexpressions in the above example, but in general it's not the case, unfortunately]
4) threads access the same common matrix of expressions, but two threads will never access the same cell.
This does NOT guarantee that you (or GiNaC on your behalf) won't operate on a same (sub)expression from different threads. You *really* need a thread safe (or atomic) reference counting to solve this problem.
I think the only problem (in his setup) is a possible call to the gcd code.
As far as I understand GCD code is not any worse in this regard (that said, it's not any better either). I might be wrong (I'm just a human being), so I'd be grateful if someone could point out any non-reentrant code in GCD routines.
I'm afraid locks will ruin any performance gains. I mean, if you need to take a lock every time you need to add two and integers or allocate several bytes of RAM, you can't achive any reasonable performance.
You were right if you made ginac thread-safe in a naive way, i.e. many locks protecting refcounting, functions, etc.
I have some experience with those `somewhat thread safe' libraries, therefore I strongly dislike this kind of ... cleverness (let's put it this way). Best regards, Alexei