Variants use in concurrent applications is not convenient, as variants must all be created (via a cloneVariant call) before any variant is actually used.
This is not always possible, when you don't know beforehand how many variants you are gonna use, or if you want to clone a variant created after that initialization step.
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem
Calls to cloneVariant on the same network instance in 2 concurrent threads, after having called allowMultiThreadVariant, will end up in exceptions.
What is the expected behavior?
Ideally, we should be able to create new variants while using other ones in concurrent threads.
A possible solution is to change the way variant variables are stored in the Network implementation. Today, each equipment stores its own variant variables in a small list/array of values. An alternative is to have instead, for each variant and each variables, a larger array to store values for all equipments in the network. For instance, for target power of generators, we would have a list of lists List<TDoubleList> targetP of size (1, 100) when there is only one variant and 100 generators, or (2, 100) if there is 2 variants.
Then, cloning a variant is only adding a new TDoubleList at the end of the list, which will be a copy of another one in the list. This can be thread-safe by using a CopyOnWriteArrayList.
Operations on one variant will always be thread safe since it will not interact with arrays representing other variants.
That approach has several advantages:
thread safe use of variants, as explained above
improved memory efficiency : less overhead since we don't have anymore XXX small arrays, but fewer large arrays
improved cache effficiency : tight loops over variant variables (think load flow) will be more efficient due to a better use of processor cache, direct consequence of the contiguous layout of variable values
Note: for reasons 2 and 3, the approach could also be interesting for non-variant equipment characteristics.
What is the motivation / use case for changing the behavior?
Use of network variants in concurrent applications, and marginally performances in computation tools.
Feature.
Variants use in concurrent applications is not convenient, as variants must all be created (via a cloneVariant call) before any variant is actually used.
This is not always possible, when you don't know beforehand how many variants you are gonna use, or if you want to clone a variant created after that initialization step.
Calls to cloneVariant on the same network instance in 2 concurrent threads, after having called allowMultiThreadVariant, will end up in exceptions.
Ideally, we should be able to create new variants while using other ones in concurrent threads.
A possible solution is to change the way variant variables are stored in the Network implementation. Today, each equipment stores its own variant variables in a small list/array of values. An alternative is to have instead, for each variant and each variables, a larger array to store values for all equipments in the network. For instance, for target power of generators, we would have a list of lists
List<TDoubleList> targetP
of size (1, 100) when there is only one variant and 100 generators, or (2, 100) if there is 2 variants.Then, cloning a variant is only adding a new TDoubleList at the end of the list, which will be a copy of another one in the list. This can be thread-safe by using a CopyOnWriteArrayList.
Operations on one variant will always be thread safe since it will not interact with arrays representing other variants.
That approach has several advantages:
Note: for reasons 2 and 3, the approach could also be interesting for non-variant equipment characteristics.
Use of network variants in concurrent applications, and marginally performances in computation tools.