You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
However, one may quickly realize that the approach is, by design, incompatible with multi-threading:
To compute one Gröbner basis over QQ with multiple threads, during the secondary modular phase, {re,}set_function_pointers may simultaneously modify a same address, or other functions can access the address on the same time: even if the data is the same, this remains absolutely UB.
This has become a real problem in recent weeks, and is now prohibited in #279. However, this means that
To compute one Gröbner basis over QQ with multiple threads, it is impossible to choose prime numbers with radically different bitsizes.
It is impossible to simultaneously compute two Gröbner bases, one over QQ and the other over small finite fields, using different threads of the same process.
A reproducer in Julia can be easily adapted from Parallel computation on multiple threads causes segfaults AlgebraicSolving.jl#111; for a reproducer in C++, simply ask your favourite LLM.
To resolve these issues, the simplest solution is to point these global function pointers to immutable methods that perform the dispatches internally. However, this will change the C interface: for example, initial_input_cmp does not have md_t *st as an argument, so it does not know st->mo for dispatch unless we duplicate it in void *ht (see #289). Furthermore, since the dispatching must be done on each call, the performance impact remains uncertain.
Another solution is to make function pointers local to each thread, but this will obviously involve a major refactor and will further modify the C interface.
msolve currently depends on mutable global function pointers for algorithm dispatches. An example is
msolve/src/neogb/data.h
Lines 447 to 451 in ff6fb15
Here, depending on the value of
st->ht, the functions{re,}set_function_pointersset the global pointers to one ofinitial_input_cmp_{be,lex,drl}.msolve/src/neogb/io.c
Lines 886 to 888 in ff6fb15
However, one may quickly realize that the approach is, by design, incompatible with multi-threading:
{re,}set_function_pointersmay simultaneously modify a same address, or other functions can access the address on the same time: even if the data is the same, this remains absolutely UB.This has become a real problem in recent weeks, and is now prohibited in #279. However, this means that
What's worse, with or without #279,
A reproducer in Julia can be easily adapted from Parallel computation on multiple threads causes segfaults AlgebraicSolving.jl#111; for a reproducer in C++, simply ask your favourite LLM.
To resolve these issues, the simplest solution is to point these global function pointers to immutable methods that perform the dispatches internally. However, this will change the C interface: for example,
initial_input_cmpdoes not havemd_t *stas an argument, so it does not knowst->mofor dispatch unless we duplicate it invoid *ht(see #289). Furthermore, since the dispatching must be done on each call, the performance impact remains uncertain.Another solution is to make function pointers local to each thread, but this will obviously involve a major refactor and will further modify the C interface.
Let me know what you think.