Re: [eigen] ThreadSafety of Eigen? |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: Re: [eigen] ThreadSafety of Eigen?
- From: Benoit Jacob <jacob.benoit.1@xxxxxxxxx>
- Date: Wed, 31 Mar 2010 10:11:48 -0400
- Cc: Gael Guennebaud <gael.guennebaud@xxxxxxxxx>
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :date:received:message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=3s8EDdfDq3dDMv6ZRmTVR/Oo/JwpRLA+aNDTwoQ08fo=; b=GpSjodplIy+oKCKDVe9ntmWOhCQ+TVqPjna9eWSQqLo8zEZJyEJh52i+VldQhEUlFL HPa1eJgyNnKtD0KZRbE7bmdCaU7A7yX7oYtwgsfYlv1VuYg8D2ox+PHIgHX2mtMy/w2o vZG1kGJgvJahI/MgIggBWfP8U5F7R6PZv6fRM=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; b=DD7W8NSdpnLXhX20XQdMXZ6/trTbsOkC6nTINbGgUEWX/6Oz46Q/7/0kU4yqIBgBuU mbROMTPHlQneJaP3/GezuMauSK34TDoazfvylaAWLxhNtzpTuagcfWPUSd9FJ6vm0Eb8 HcN7ENJFVuRzEodHPa8gb/T2naX8GBkkKO4YE=
2010/3/31 Björn Piltz <bjornpiltz@xxxxxxxxxxxxxx>:
> Some thoughts on the subject:
> Benoit is saying that Eigen is reentrant - as it should be. That is what
> most people mean by thread-safe, even if it isn't thread safe in the sense
> that different threads can safely manipulate the same matrix.
> However, this isn't entirely true.
> <begin nitpicking>
> There are a couple of problematic uses of static data in Eigen.
> There are numerous uses of const static global or member variables. e.g
> static _EIGEN_DECLARE_CONST_FAST_Packet4f(ZERO, 0);
OK, i didn't think of that. As you say it's not problematic as it
doesn't change.
> or
> class MatrixFunction{
> static const int Rows = Traits::RowsAtCompileTime;
That one is a mistake: it should be an enum. Let's fix that. Making it
a "static const int" is just giving the compiler the additional work
of having to understand that it can optimize it away at compile time.
> These are unproblematic, since these variables are initialized at program
> start and never change. One only has to consider the "static initialization
> order fiasco" - but that is hardly a risk here - and the runtime overhead at
> startup, which should be minimal for these examples. There are a couple of
> globals in src/Core/arch/AltiVec/PacketMath.h which haven't been marked as
> const even though they should be, but that's an easy fix.
> The finer subtleties occur in examples where static variables are declared
> in a function. These variables will be initialized lazily. i.e. the first
> time the function is called.
> The use of static variables in blueNorm() in src/core/stablenorm.h is just
> plain wrong. The good news is that this is the only example I found of
> blatant non-reentrancy.
(pinging Gael as I believe he copied that code from elsewhere)
> MatrixBase<Derived>::blueNorm() const
> {
> static int nmax = -1;
> static RealScalar b1, b2, s1m, s2m, overfl, rbig, relerr;
> if(nmax <= 0)
> {
> // calculate b1, b2, etc
> ...
> nmax = nbig;
> }
OK indeed this is not reentrant! Thanks for spotting it. For Gael.
> An even subtler example would be:
> QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>&
> other) const
> {
> static const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
> ...
> This example is almost certainly safe, at least as long Scalar is a POD. The
> problem is that either the expression is so simple the compiler optimizes it
> away - in which case there is no reason declaring it static - or it isn't..
This one for Gael too :)
Benoit
> Then it might actually be inefficient, because there is a runtime check,
> which involves locking(GCC and MSVC treat these cases differently), to see
> if the variable has been initialized or not.
> The fact is that *there is no way to use lazily initialized non-POD static
> variables that does not include locks or some atomic API*.
> For reference,
> see http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf and http://stackoverflow.com/questions/6915/thread-safe-lazy-contruction-of-a-singleton-in-c
> So, to return to blueNorm(), I see two ways of fixing this
> A: Mark the function as non-reentrant. This would be Eigen's only such
> function then, or
> B: Put b1, b2 etc in a class, a global instance of which will be initialized
> at startup. I think this initialization might be optimized away in programs
> that never call the function(that needs to be checked).
> Don't be tempted to stick to lazily initialization(through double-checked
> locking or something equally clever), since it just isn't thread-safe.
> To end this mail on a positive note: reentrancy is actually one of the
> reasons I decided to switch to Eigen in the first place, after having used
> numerous other libraries lacking in this respect.
> best
> Björn