Feature #142
Improve threadsafety
Description
Currently CoCoALib can be made (largely?) threadsafe by compiling with the flag -DCoCoA_THREADSAFE_HACK
. As its name suggests it is a hack rather than a proper solution to the problem.
This hack involves disabling memory allocation by MemPool
by #defining MemPool
to be MemPoolFake
which simply forwards all requests to the C++ memory manager (::operator new
and ::operator delete
).
The hack also disables reference counting, so all ref counted objects live forever. Naturally this causes some memory leaks (see issue #141).
Related issues
History
#1 Updated by John Abbott about 12 years ago
ring
. Two likely additions are:
- an RAII class for "local" rings
- an explicit "destroy" command for rings
#2 Updated by Anna Maria Bigatti about 12 years ago
John Abbott wrote:
No doubt the problem is due to the temporary rings (inside
Elim
) not self destroying when they're no longer needed -- ref counting is disabled when the threadsafety hack is forced.
Elim
(and a few other functions) create a temporary ring.
I think we should have a way to destroy a (temporary) ring to be called at the end of the function. In fact it would do nothing when ref counting is on (just check it is really destroyable).
The only danger is that inside a child call a global variable (bad for thread-safety anyway) is defined, is that correct?
#3 Updated by John Abbott about 12 years ago
Anna Maria Bigatti wrote:
Elim
(and a few other functions) create a temporary ring.
Yes. Temporary rings are a common idiom. It would be nice to have an easy way of handling them correctly (probably via RAII).
I think we should have a way to destroy a (temporary) ring to be called at the end of the function. In fact it would do nothing when ref counting is on (just check it is really destroyable).
This is what the RAII approach should do.
The only danger is that inside a child call a global variable (bad for thread-safety anyway) is defined, is that correct?
Anna clarified this last comment: the "danger" is that an incautious programmer could leave an element of the temporary ring in a global variable, which would then lead to "undefined behaviour" when that global is altered. The solution is easy: don't use globals :-)
#4 Updated by Anna Maria Bigatti over 11 years ago
- Category set to Safety
#5 Updated by John Abbott over 10 years ago
- Status changed from New to In Progress
- % Done changed from 0 to 50
#6 Updated by Anna Maria Bigatti over 10 years ago
- Target version set to CoCoALib-0.99533 Easter14
#7 Updated by John Abbott about 10 years ago
- Target version changed from CoCoALib-0.99533 Easter14 to CoCoALib-0.99534 Seoul14
#8 Updated by John Abbott almost 10 years ago
- Target version changed from CoCoALib-0.99534 Seoul14 to CoCoALib-1.0
#9 Updated by John Abbott almost 9 years ago
I wonder whether the default configuration for CoCoALib should be the threadsafe one (which incurs a run-time efficiency penalty).
Currently the default is not threadsafe.
What do you think?
#10 Updated by John Abbott over 8 years ago
After looking around on internet it seems that C++98 has no portable way of dealing with threadsafety, but C++11 (and later versions) does.
Probably the "threadsafe hack" should be migrated to a proper threadsafe option, presumably controlled by a pre-compilation flag CoCoA_THREADSAFE
. This implies that default compilation (without setting that flag) would be only single-threaded. Setting the option also implies that compilation is of C++11.
#11 Updated by John Abbott over 8 years ago
I spoke to Mario this morning about threadsafety in CoCoALib (also thinking about Mario's new code which has just been adjoined to the CVS repository).
Mario liked the idea of a single flag, tentatively called CoCoA_THREADSAFE
, which when set will produce threadsafe code (but which also requires a C++11 compiler); if the flag is not set then the resulting executable is not guaranteed to be threadsafe, but it should be possible to compile with a C++03 compiler (for the time being).
Comments? Suggestions? Other ideas?
#12 Updated by John Abbott over 8 years ago
I wonder whether CoCoA_THREADSAFE
is to be just a temporary measure. Presumably at some point practically all compilers will accept C++11. The main question would then be whether the threadsafety measures incur a significant run-time cost during single-threaded execution; if not, then presumably the preprocessor flag will no longer serve any useful purpose (except perhaps for obfuscated code competitions?).
#13 Updated by John Abbott over 5 years ago
- Related to Design #1259: ThreadsafeCounter is now obsolete? added
#14 Updated by John Abbott over 4 years ago
- Related to Design #1225: Move to C++14 (skipping C++11) added
#15 Updated by John Abbott over 3 years ago
I now think that it is probably better to default to threadsafe code; the user must configure with "not threadsafe" to obtain (presumably faster) non-threadsafe compilation.
Note that when releasing CoCoA-5 we can opt for the "fast, not threadsafe" compilation since CoCoA-5 itself is single-threaded.
If we do follow this proposal, what should the "not threadsafe" option be called?
#16 Updated by John Abbott over 3 years ago
SmartPtrIRC
so that an std::atomic<std::size_t>
is used for the ref count instead of std::size_t
.I tried just one speed test:
- non-threadsafe took about 14.7s to run all the tests in
src/tests/
- threadsafe took about 16.1s
So for this 1 test suite, threadsafe was about 10% slower.
I would expect that some computations with many ring elems in a small finite field could incur a significantly greater overhead.
So it is likely worth offering a way to compile non-threadsafe code.
MemPool
,OrdvArith
,SmartPtrIRC
,NumTheory-prime.C
,PPMonoidOV.C
Rectifying NumTheory-prime.C
might be time-consuming (currently it is unsafe).
#17 Updated by John Abbott over 3 years ago
- Target version changed from CoCoALib-1.0 to CoCoALib-0.99850
--allow-non-threadsafe
for theconfigure
scriptCoCoA_ALLOW_NON_THREADSAFE
as the corresponding CPP identifier
There is a potentially non-obvious dependency: to use MemPool
memory mgt, you must allow non-threadsafe compilation.
This means that unless CoCoA_ALLOW_NON_THREADSAFE
is defined, MemPool will actually refer to MemPoolFake
(which just forwards all requests to operator new
)
#18 Updated by John Abbott over 3 years ago
- Related to Bug #1522: SEGV: avoid long linked lists of loaves in MemPools added
#19 Updated by John Abbott 3 months ago
- Target version changed from CoCoALib-0.99850 to CoCoALib-0.99880