This is the mail archive of the
mailing list for the GCC project.
Re: Re: [GSoC'19, libgomp work-stealing] Task parallelism runtime
- From: Jakub Jelinek <jakub at redhat dot com>
- To: 김규래 <msca8h at naver dot com>
- Cc: gcc at gcc dot gnu dot org
- Date: Mon, 5 Aug 2019 12:32:16 +0200
- Subject: Re: Re: [GSoC'19, libgomp work-stealing] Task parallelism runtime
- References: <email@example.com> <firstname.lastname@example.org> <20190713062848.GE2125@tucnak> <email@example.com> <20190722185413.GA13123@laptop.zalov.cz> <firstname.lastname@example.org> <email@example.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Sat, Aug 03, 2019 at 06:11:58PM +0900, 김규래 wrote:
> I'm currently having trouble implementing the thread sleeping mechanism when the queue is out of tasks.
> Problem is, it's hard to maintain consistency between the thread sleeping routine and the queues.
> See the pseudocode below,
> 1. check queue is empty
> 2. go to sleep
> if we go lock-free, the consistency between 1 and 2 cannot be maintained.
I thought we don't want to go lock-free, the queue operations aren't easily
implementable lock-free, but instead with a lock for each of the queues,
so in the multi-queue setting having locks on the implicit tasks that hold
those queues. What can and should be done without lock is perhaps some
preliminary check if a queue is empty, that can be done through
And, generally go to sleep is done outside of the critical section, inside
of the critical section we decide if we go to sleep or not, and then
go to sleep either (on Linux) using futexes, or otherwise using semaphores,
both have the properties that one can already post to them before some other
thread sleeps on it, and in that case the other thread doesn't actually go
to sleep. The wake up (post on the semaphore or updating the memory + later
futex wake) is sometimes done inside of a critical section, the updating of
memory if it is not atomic increase/decrease and the latter depending on
whether we remember from the atomic operation whether the wake up is needed
or not and defer it until after the critical section.
do_wake = team->task_running_count + !parent->in_tied_task
gomp_team_barrier_wake (&team->barrier, 1);
you can see the wake up is done outside of the critical section.
If team->task_lock isn't used, there will be of course problems, say
team->task_count and team->task_queued_count need to be bumped atomically,
ditto operations on team->barrier, and the question is what to do with the
team->task_running_count check, if that one is updated atomically too,
maybe __atomic_load might be good enough, though perhaps worst case it might
mean we don't in some cases wake anybody, so there will be threads idling
instead of doing useful work, but at least one thread probably should handle