-
Notifications
You must be signed in to change notification settings - Fork 207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tiling processor segfaults when multithreading is enabled #1929
Comments
I think there is a general problem here. The tiling processor works in a way that it executes code pieces on each tile. The code pieces are written in KLayout's "expressions" notation. The main reason for that is that this provides a certain level of multi thread safety. Hence, multiple tiles can be worked on in parallel. The results of the tile actions are finally queued, reordered and sent to a single-threaded output stage. This scheme is safe as long as the tiled operations do not modify the layout the tiling processor works on. The Layout object is thread-safe while reading, but not, while writing. This is true for all reading operations - specifically those which pull the tile's content into a Region object and act on it, before sending the results the single-threaded output channel. This is the main use case of the tiling processor. I assume that the "fill_tiled" implementation deviates from this scheme by performing some "fill_region" which will modify the layout. That causes the crash I assume. The solution is not straightforward. The easiest way is to put a lock around "fill_region", but that lock is also needed for the read operations as they are not thread-safe when another thread is writing. In the end, that will boil down to single-threaded operation. A solution conforming to the concept was to establish an output channel that does the tiling. But again, that would degrade the performance to single-threaded mode. I think a somewhat weird, yet feasible solution is to set up a small Layout per tile, deliver the fill cells there and send these layouts to an output channel that finally assembles these pieces into the output layout. That would at least enable multiple threads for the bulk of the fill operation, which is computing the fill arrays. The assembly step is single-threaded though. I will give that a try. Matthias |
Here is an experiment. The following code is a multi-core capable implementation of a filling tiling processor:
For input I used the Sky130 Caravel chip. Runtimes are in my case:
and
So it basically seems to scale nicely. Assembly times are small compared to the computation times for the fill + boolean. Matthias |
Hi Matthias, The code in question is directly calling the kfactory code here https://github.com/gdsfactory/kfactory/blob/main/src%2Fkfactory%2Futils%2Ffill.py I used and adopted an old forum post for this, where you gave an example on how to use it. So, is your recommendation to defer the output receiver filling the layout until all sub-regions are finished with calculating the regions needed for filling? I guess I could modify it to do so. Though I have to say, I have used this plenty of times without issue on linux (with CI runners from 1-2 cores up to my machine with 16 cores / 32 threads) and it never segfaulted like this. And I have done weird stuff like use it for very low density fills (we had some requirents for certain cells being in every region, but also not too densly) Best, |
Yes, I am sorry. I probably missed that detail before. Threading issues are a nightmare. They may never happen and suddenly someone manages to trigger it all the time. Actually the Layout object is "mostly" thread safe, but if one thread pours in fill cell instances while the other one reads the same hierarchy at the same time, bad things will happen. Better to play safe. Matthias |
I see, that makes sense, thanks! Best, |
Thanks for all the investigating and info! Should I close this out and open a corresponding issue with kfactory? Or do we want to leave this open pending further safety around the tiling processor in klayout? |
I don't think there is a lot of room for improvement on klayout's side. The problem boils down to the following, which even in standard python ) leads to either very unexpected results, early termination, or segfaults (forgot which one, I believe the first one): list = [j for j in range 20]
for i, el in enumerate():
if i % e == 0:
del _list[i]
print(i, el) Only here it's the other way around as it's inserting instead of deleting elements. It's just a bad idea to iterate through mappings/linked lists while modifying it. I was wondering whether that wouldn't cause any problems when I read that forum post, but assumed that probably |
@klayoutmatthias is it save to use region fill withreturning the remaining to be filled area returned and filled in a while loop while in the |
@edelmanjm could you try the new version of kfactory and see whether it fixes your segfault? I implemented Matthias' suggestion with the temp layout (which hopefully speeds it up as well, if only slightly). |
Hi all, currently using klayout via gdsfactory, and I've run into an issue when calling
fill.fill_tiled()
withn_threads > 1
where klayout segfaults. I believe this is an issue in klayout itself based on the stacktrace and apparent threading behavior, but I haven't had time to fully root-case everything. Here's a sample backtrace, with the full log attached:I'm currently able to consistently reproduce this issue, but I haven't had time to write up a minimal example and debug it using ThreadSanitizer. If there's the desire for me to do so/I have the time, I'd be happy to delve into it a little later, but I just don't have the time right this second. Mostly posting here for visibility. Thanks!
crash.txt
The text was updated successfully, but these errors were encountered: