OpenSTA currently is not thread-safe.
If you run the OpenROAD flow in multi-threaded mode (pass OR_ARGS='-threads $(nproc)' to make) you can easily get a data race, often resulting in an infinite loop or segfault, e.g.:
Signal 11 received
Stack trace:
0# 0x00005574A338B47F in /home/krzysztof/OpenROAD-flow-scripts/tools/install/OpenROAD/bin/openroad
1# 0x00007F80C145C710 in /usr/lib/libc.so.6
2# std::_Rb_tree_insert_and_rebalance(bool, std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::_Rb_tree_node_base&) in /usr/lib/libstdc++.so.6
3# sta::Network::drivers(sta::Net const*) in /home/krzysztof/OpenROAD-flow-scripts/tools/install/OpenROAD/bin/openroad
4# sta::GraphDelayCalc::findMultiDrvrNet(sta::Vertex*) in /home/krzysztof/OpenROAD-flow-scripts/tools/install/OpenROAD/bin/openroad
5# sta::GraphDelayCalc::findDriverDelays(sta::Vertex*, sta::ArcDelayCalc*) in /home/krzysztof/OpenROAD-flow-scripts/tools/install/OpenROAD/bin/openroad
6# sta::GraphDelayCalc::findVertexDelay(sta::Vertex*, sta::ArcDelayCalc*, bool) in /home/krzysztof/OpenROAD-flow-scripts/tools/install/OpenROAD/bin/openroad
7# 0x00005574A36F3B46 in /home/krzysztof/OpenROAD-flow-scripts/tools/install/OpenROAD/bin/openroad
8# sta::DispatchQueue::dispatch_thread_handler(unsigned long) in /home/krzysztof/OpenROAD-flow-scripts/tools/install/OpenROAD/bin/openroad
9# 0x00007F80C16E1943 in /usr/lib/libstdc++.so.6
10# 0x00007F80C14AA9EB in /usr/lib/libc.so.6
11# 0x00007F80C152E7CC in /usr/lib/libc.so.6
This is from the 5_1_grt target, not sure if it happens in other stages.
This stack trace starts in the dispatcher, but the real story is this:
This insertion is not thread-safe. This PR gets rid of this map in Network, as it seems to only be used there for caching. In ConcreteNetwork, it adds synchronization to code that accesses this map in a multi-threaded context.
Below is a performance regression check on 5_1_grt.
OpenSTA currently is not thread-safe. If you run the OpenROAD flow in multi-threaded mode (pass
OR_ARGS='-threads $(nproc)'
tomake
) you can easily get a data race, often resulting in an infinite loop or segfault, e.g.:This is from the
5_1_grt
target, not sure if it happens in other stages.This stack trace starts in the dispatcher, but the real story is this:
GraphDelayCalc::findDelays(...)
callsBfsIterator::visitParallel
:As the name implies,
BfsIterator::visitParallel
is multi-threaded. It calls (in this case)FindVertexDelays::visit(...)
from multiple threads.FindVertexDelays::visit(...)
callsGraphDelayCalc::findVertexDelay(...)
:GraphDelayCalc::findVertexDelay(...)
callsGraphDelayCalc::findDriverDelays(...)
:GraphDelayCalc::findDriverDelays(...)
callsGraphDelayCalc::findMultiDrvrNet(...)
:GraphDelayCalc::findMultiDrvrNet(...)
callsNetwork::drivers(const Pin*)
:Network::drivers(const Pin*)
callsNetwork::drivers(const Net*)
:Network::drivers(const Net*)
inserts into what's basically anstd::map
.This insertion is not thread-safe. This PR gets rid of this map in
Network
, as it seems to only be used there for caching. InConcreteNetwork
, it adds synchronization to code that accesses this map in a multi-threaded context.Below is a performance regression check on
5_1_grt
.Ibex
ibex
/5_1_grt
/master
ibex
/5_1_grt
/thread-safe-network
ibex
/5_1_grt
/master
ibex
/5_1_grt
/thread-safe-network
BlackParrot
black_parrot
/5_1_grt
/master
black_parrot
/5_1_grt
/thread-safe-network