Hi,

I have a few annoying problems trying to optimize building the nextpnr package.

First of all, the build uses LTO, so the linker spawns a parallel sub-make to build LTO objects, and expects a job server, but if I build with -j1, no jobserver is created, and this sub-make is started with a concurrency level equal to the number of CPUs.

That is only slightly annoying in most cases, and slightly beneficial in others. I just notice it because I often use -j1 to avoid swap thrashing.

The package builds a set of database files, using a tool that consumes a *lot* of RAM, the amount is different for each database file, so there is no optimum setting.

I currently use a pessimistic "available system RAM divided by 5 GB, but at least 1", which often enough comes out to exactly 1 (so I notice that LTO doesn't respect the limit), so it serializes even those database builds that *would* fit in memory.

That's a few extra hours of build time, but increasing concurrency also adds a few hours of build time on the machines that still use harddisks.

In addition, there usually is enough memory to compile *some* programs in parallel (the compiler doesn't need that much), but increasing concurrency goes into "build more databases" first.

Because building the databases takes the most amount of time, that is also almost correct. With 7 GB RAM and

    all: \
        database-1-5G database-2-5G database-3-4G \
        database-4-2G database-5-1G main-1 main-2 main-3

the behaviour I'd like to see is

1. database-1-5G and database-4-2G

2. when database-4-2G finishes, start database-5-1G and main-1 (1 thread)

3. when database-5-1G finishes, give one more thread to main-1

4. when database-1-5G finishes, start database-2-5G

5. when database-2-5G finishes, start database-3-4G and give one more thread to main-1.

6. when database-3-4G finishes, give four more threads to building the main program.

Is there a good way to give tasks a "weight" that does not lead to them starving? I.e. if I wrap "database-1-5G" in a tool that pretends to be a sub-Make and consumes four additional tokens before starting, there is a good chance that this works for the first invocation, but returning the tokens to the pool, they will get snatched up by four compile tasks, not database-2-5G.

Of course, I can wait until I get these four tokens back, but I'd expect the following to happen:

1. I wait for four tokens
2. one compile job exits, returns a token
3. I get one token
4. the next compile job goes into the queue for the next token
5. I get into the queue for the next token

so draining the token pool will take a while, and block compiles in the meantime. Plus, I'd also have to accurately know how many tokens are in play, so I don't deadlock (e.g. with 4 GB RAM, I still need to start the 5GB jobs -- they will swap, but I can't help that).

Are there any better ideas?

   Simon

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to