[gomp4] openacc kernels directive support
Tom de Vries
Tom_deVries@mentor.com
Wed Aug 6 15:10:00 GMT 2014
Jakub,
I've looked into how to implement the openacc kernels directive in gcc.
In order to map the loopnests marked by the kernels directive efficiently on
accelerator hardware, we need parallelization and vectorization.
Focussing on paralellization for the moment, a possibility for paralellization
is to use the parloops pass. The parloops pass identifies loops that can be
parallelized with a factor n, splits off the n-reduced loop into a function and
issues the function in n parallel threads.
A problem with using parloops for the kernels directive is that the parloops
pass is placed after lto's gimple-stream read/write point, so the parloops pass
is executed during the accelerator-specific compilation. So while the resulting
function with the reduced loop is compiled for the accelerator as required, also
the code issuing the function in parallel threads is generated for the
accelerator. While f.i. newer cuda with dynamic parallelism supports launching
accelerator kernels from within accelerator kernels, I guess that that might not
hold in general.
I've investigated moving the parloops pass up in the pass list, using attached
example kernels.c. It contains 4 loops; 2 loops that set arrays, one loop that
does a vector addition, and one loop that does a reduction
First, I compile the example using upstream trunk:
...
$ gcc -ftree-parallelize-loops=32 -fdump-tree-all-all -O2 kernels.c -std=c99
-Wl,-rpath,$(pwd -P)/lean-c/install/lib64
$ ./a.out ; echo $?
sum: 4293394432
0
...
All 4 loops are recognized as parallel by parloops:
...
$ egrep 'SUCCES|FAIL' kernels.c.*parloops
SUCCESS: may be parallelized
SUCCESS: may be parallelized
SUCCESS: may be parallelized
SUCCESS: may be parallelized
...
Using attached patch, I manage the same with parloops placed after
pass_build_ealias, with some additional passes inbetween:
...
NEXT_PASS (pass_build_ealias);
NEXT_PASS (pass_ch);
NEXT_PASS (pass_ccp);
NEXT_PASS (pass_lim_aux);
NEXT_PASS (pass_parallelize_loops);
...
The pass_lim_aux in front is needed because otherwise the loads of pointers a, b
and c stay in the loop and prevent parallelization.
The pass_ccp is to get rid of:
...
phi is i_5 = PHI <0(3)>
arg of phi to exit: value 0 used outside loop
checking if it a part of reduction pattern:
FAILED: it is not a part of reduction.
...
The pass_tree_ch is to get rid of:
...
phi is sum_3 = PHI <sum_1(4)>
arg of phi to exit: value sum_1 used outside loop
checking if it a part of reduction pattern:
FAILED: it is not a part of reduction.
...
The place after build_ealias is early enough to be before the lto-stream
write/read. I don't see how we can do this earlier. Before ealias, there's no
alias info, and one of the loops fails to be recognized as parallel.
Furthermore, pass_ch, pass_ccp, pass_lim_aux and pass_parloops are written to
work on cfg/ssa code, which we don't have at omp_low/omp_exp time.
We could insert a pass-group here that only deals with functions that have the
kernels directive, and do the auto-par thing in a pass_oacc_kernels (which
should share the majority of the infrastructure with the parloops pass):
...
NEXT_PASS (pass_build_ealias);
INSERT_PASSES_AFTER/WITHIN (passes_oacc_kernels)
NEXT_PASS (pass_ch);
NEXT_PASS (pass_ccp);
NEXT_PASS (pass_lim_aux);
NEXT_PASS (pass_oacc_par);
POP_INSERT_PASSES ()
...
Any comments, ideas or suggestions ?
Thanks,
- Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: kernels.c
Type: text/x-csrc
Size: 812 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc/attachments/20140806/bc2820eb/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: move-parloops.patch
Type: text/x-patch
Size: 4847 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc/attachments/20140806/bc2820eb/attachment-0001.bin>
More information about the Gcc
mailing list