On Tue, Jun 09, 2015 at 22:24:26 +0200, Jakub Jelinek wrote:
> On Tue, Jun 09, 2015 at 09:36:08PM +0300, Ilya Verbin wrote:
> > I don't quite understand from "If a depend clause is present, then it is 
> > treated
> > as if it had appeared on the implicit task construct that encloses the 
> > target
> > construct", is
> > 
> >   #pragma omp target depend(inout: x)
> > 
> > equivalent to
> > 
> >   #pragma omp task depend(inout: x)
> >   #pragma omp target
> > 
> > or not?
> > 
> > In other words, can't we just generate GOMP_task (...) with GOMP_target 
> > (...)
> > inside, without any new arguments?
> 
> No, that would be an explicit task.  Furthermore, the implicit task isn't
> on the host side, but on the offloading device side.  The implicit task is
> what is executed when you enter the #pragma omp target.  Ignoring the teams
> construct which is there mainly for NVidia GPGPUs, when you enter the
> #pragma omp target construct, there is an implicit parallel with
> num_threads(1) (like there is an implicit parallel with num_threads(1)
> when you enter main () of a host program), and that implicit parallel has
> a single implicit task, which executes the statements inside of #pragma
> omp target body, until you encounter #pragma omp teams or #pragma omp
> parallel.  And the above statement simply says that no statements from
> the #pragma omp target body are executed until the depend dependency is
> satisfied.  Whether these dependencies are host addresses, or offloading
> device addresses, is something that really needs to be figured out, I admit
> I haven't read the whole async offloading text carefully yet, nor
> participated in the telecons about it. 

So, as I understood, three tasks will be generated almost simultaneously in
foo1: one on host and two on target.
Target task 1 will be executed immediately.
Host task will wait for task 1 to be completed on target.
(Or it is not possible to mix "omp target" and "omp task" dependencies?)
And task 2 will wait on target for task 1.

void foo1 ()
{
  int x;

  #pragma omp parallel
  #pragma omp single
    {
      #pragma omp target nowait depend(out: x)
        fprintf (stderr, "target task 1\n");

      #pragma omp task depend(in: x)
        fprintf (stderr, "host task\n");

      #pragma omp target depend(in: x)
        fprintf (stderr, "target task 2\n");
    }
}

I just can't understand why do we need target tasks, i.e. why a host task with a
target region inside can't wait for another host task, like in foo2?

void foo2 ()
{
  int x;

  #pragma omp parallel
  #pragma omp single
    {
      #pragma omp task depend(out: x)
      #pragma omp target
        fprintf (stderr, "host task with tgt 1\n");

      #pragma omp task depend(in: x)
        fprintf (stderr, "host task\n");

      #pragma omp task depend(in: x) 
      #pragma omp target
        fprintf (stderr, "host task with tgt 2\n");
    }
}

Thanks,
  -- Ilya

Reply via email to