Message ID | 530648F8.2010409@codesourcery.com |
---|---|
State | New |
Headers | show |
2014-02-20 22:27 GMT+04:00 Bernd Schmidt <bernds@codesourcery.com>: > There were still a number of things in these patches that did not make sense > to me and which I've changed. Let me know if there was a good reason for the > way some of these things were originally done. > * Functions and variables now go into different tables, otherwise > intermixing between them could be a problem that causes tables to > go out of sync between host and target (imagine one big table being > generated by ptx lto1/mkoffload, and multiple small table fragments > being linked together on the host side). What do you mean by multiple small table fragments? The tables from every object file should be joined together while linking DSO in the same order for both host and target. If you need to join tables from multiple target images into one big table, the host tables also should be joined in the same order. In our case we're obtaining each target table while loading the image to target device, and merging it with a corresponding host table. How splitting functions and global vars into 2 tables will help to avoid intermixing? > * Is there a reason to call a register function for the host tables? > The way I've set it up, we register a target function/variable table > while also passing a pointer to the __OPENMP_TARGET__ symbol which > holds information about the host side tables. Suppose there is liba, that depends on libb, that depends on libc. Also corresponding target image tgtimga depends on tgtimgb, that depends on tgtimgc. When liba is going to start offloaded function, it calls GOMP_target with a pointer to its descriptor, which contains a pointer to tgtimga. But how does GOMP_target know that it should also load tgtimgb and tgtimgc to target? And where to get their descriptors from? That's why we have added host-side DSO registration. In this example they are loaded on host in the following order: libc, libb, liba. In the same order they are registered in libgomp, and loaded to target device while initialization. In the same order the tables received from target are merged with the host tables from the descriptors. > I'm appending those parts of my current patch kit that seem relevant. This > includes the ptx mkoffload tool and a patch to make a dummy > GOMP_offload_register function. Most of the others are updated versions of > patches I've posted before, and two adapted from Michael Zolotukhin's set > (automatically generated files not included in the diffs for size reasons). > How does this look? I will take a closer look at you changes, try to run it, and send feedback next week. -- Ilya
On 02/21/2014 04:17 PM, Ilya Verbin wrote: > 2014-02-20 22:27 GMT+04:00 Bernd Schmidt <bernds@codesourcery.com>: >> There were still a number of things in these patches that did not make sense >> to me and which I've changed. Let me know if there was a good reason for the >> way some of these things were originally done. >> * Functions and variables now go into different tables, otherwise >> intermixing between them could be a problem that causes tables to >> go out of sync between host and target (imagine one big table being >> generated by ptx lto1/mkoffload, and multiple small table fragments >> being linked together on the host side). > > What do you mean by multiple small table fragments? Well, suppose you have file1.o and file2.o compiled for the host with a .offload_func_table_section in each, and they get linked together - each provides a fragment of the whole table. > The tables from every object file should be joined together while > linking DSO in the same order for both host and target. > If you need to join tables from multiple target images into one big > table, the host tables also should be joined in the same order. The problem is that ptx does not have a linker, so we cannot exactly reproduce what happens on the host side. We have to process all host .o files in one single invocation of ptx lto1, and produce a single ptx assembly file, with a single function/variable table, from there. Having functions and variables separated gives us at least a small chance that the order will match that found in the host tables if the host table is produced by linking multiple fragments. > Suppose there is liba, that depends on libb, that depends on libc. What kind of dependencies between liba and libb do you expect to be able to support on the target side? References to each other's functions and variables? Bernd
2014-02-21 19:41 GMT+04:00 Bernd Schmidt <bernds@codesourcery.com>: > The problem is that ptx does not have a linker, so we cannot exactly > reproduce what happens on the host side. We have to process all host .o > files in one single invocation of ptx lto1, and produce a single ptx > assembly file, with a single function/variable table, from there. Having > functions and variables separated gives us at least a small chance that the > order will match that found in the host tables if the host table is produced > by linking multiple fragments. If ptx lto1 will process all .o files in order as they were passed to it, the resulting table should be consistent with the table produced by host's lto1. > What kind of dependencies between liba and libb do you expect to be able to > support on the target side? References to each other's functions and > variables? Yes, references to global variables and calls to functions, marked with "omp declare target".
2014-02-20 22:27 GMT+04:00 Bernd Schmidt <bernds@codesourcery.com>: > * Functions and variables now go into different tables, otherwise > intermixing between them could be a problem that causes tables to > go out of sync between host and target (imagine one big table being > generated by ptx lto1/mkoffload, and multiple small table fragments > being linked together on the host side). If you need 2 different tables for funcs and vars, we can also use them. But I still don't understand how it will help synchronization between host and target tables. > * I've put the begin/end fragments for the host tables into crtstuff, > which seems like the standard way of doing things. Our plan was that the host side descriptor __OPENMP_TARGET__ will contain (in addition to func/var table) pointers to the images for all enabled accelerators (e.g. omp_image_nvptx_start and omp_image_intelmic_start), therefore we generated it in the lto-wrapper. But if the number of accelerators and their types/names will be defined during configuration, then it's ok to generate the descriptor in crtstuff. > * Is there a reason to call a register function for the host tables? > The way I've set it up, we register a target function/variable table > while also passing a pointer to the __OPENMP_TARGET__ symbol which > holds information about the host side tables. In our case we can't register target table with a call to libgomp, it can be obtained only from the accelerator. Therefore we propose a target-independent approach: during device initialization libgomp calls 2 functions from the plugin (or this can be implemented by a single function): 1. devicep->device_load_image_func, which will load target image (its pointer will be taken from the host descriptor); 2. devicep->device_get_table_func, which in our case connects to the device and receives its table. And in your case it will return func_mappings and var_mappings. Will it work for you? > * An offload compiler is built with --enable-as-accelerator-for=, which > eliminates the need for -fopenmp-target, and changes install paths so > that the host compiler knows where to find it. No need for > OFFLOAD_TARGET_COMPILERS anymore. Unfortunately I don't fully understand this configure magic... When a user specifies 2 or 3 accelerators during configuration with --enable-accelerators, will several different accel-gccs be built? Thanks, -- Ilya
On 02/28/2014 05:09 PM, Ilya Verbin wrote: > 2014-02-20 22:27 GMT+04:00 Bernd Schmidt <bernds@codesourcery.com>: >> * Functions and variables now go into different tables, otherwise >> intermixing between them could be a problem that causes tables to >> go out of sync between host and target (imagine one big table being >> generated by ptx lto1/mkoffload, and multiple small table fragments >> being linked together on the host side). > > If you need 2 different tables for funcs and vars, we can also use > them. But I still don't understand how it will help synchronization > between host and target tables. I think it won't help that much - I still think this entire scheme is likely to fail on nvptx. I'll try to construct an example at some point. One other thing about the split tables is that we don't have to write a useless size of 1 for functions. >> * I've put the begin/end fragments for the host tables into crtstuff, >> which seems like the standard way of doing things. > > Our plan was that the host side descriptor __OPENMP_TARGET__ will > contain (in addition to func/var table) pointers to the images for all > enabled accelerators (e.g. omp_image_nvptx_start and > omp_image_intelmic_start), therefore we generated it in the > lto-wrapper. The concept of "image" is likely to vary somewhat between accelerators. For ptx, it's just a string and it can't really be generated the same way as for your target where you can manipulate ELF images. So I think it is better to have a call to a gomp registration function for every offload target. That should also give you the ordering you said you wanted between shared libraries. >> * Is there a reason to call a register function for the host tables? >> The way I've set it up, we register a target function/variable table >> while also passing a pointer to the __OPENMP_TARGET__ symbol which >> holds information about the host side tables. > > In our case we can't register target table with a call to libgomp, it > can be obtained only from the accelerator. Therefore we propose a > target-independent approach: during device initialization libgomp > calls 2 functions from the plugin (or this can be implemented by a > single function): > 1. devicep->device_load_image_func, which will load target image (its > pointer will be taken from the host descriptor); > 2. devicep->device_get_table_func, which in our case connects to the > device and receives its table. And in your case it will return > func_mappings and var_mappings. Will it work for you? Probably. I think the constructor call to the gomp registration function would contain an opaque pointer to whatever data the target wants, so it can arrange its image/table data in whatever way it likes. It would help to see the code you have on the libgomp side, I don't believe that's been posted yet? > Unfortunately I don't fully understand this configure magic... When a > user specifies 2 or 3 accelerators during configuration with > --enable-accelerators, will several different accel-gccs be built? No - the idea is that --enable-accelerator= is likely specific to ptx, where we really just want to build a gcc and no target libraries, so building it alongside the host in an accel-gcc subdirectory is ideal. For your use case, I'd imagine the offload compiler would be built relatively normally as a full build with "--enable-as-accelerator-for=x86_64-linux", which would install it into locations where the host will eventually be able to find it. Then the host compiler would be built with another new configure option (as yet unimplemented in my patch set) "--enable-offload-targets=mic,..." which would tell the host compiler about the pre-built offload target compilers. On the ptx side, "--enable-accelerator=ptx" would then also add ptx to the list of --enable-offload-targets. Naming of all these configure options can be discussed, I have no real preference for any of them. Bernd
On 28 Feb 17:21, Bernd Schmidt wrote: > I think it won't help that much - I still think this entire scheme > is likely to fail on nvptx. I'll try to construct an example at some > point. > > One other thing about the split tables is that we don't have to > write a useless size of 1 for functions. > > > The concept of "image" is likely to vary somewhat between > accelerators. For ptx, it's just a string and it can't really be > generated the same way as for your target where you can manipulate > ELF images. So I think it is better to have a call to a gomp > registration function for every offload target. That should also > give you the ordering you said you wanted between shared libraries. > > > Probably. I think the constructor call to the gomp registration > function would contain an opaque pointer to whatever data the target > wants, so it can arrange its image/table data in whatever way it > likes. Assuming that we're using the scheme with tables. Every DSO with offloading must contain a constructor call to GOMP_offload_register (const void *openmp_target); The openmp_target descriptor in every DSO will have target-independent entries (addresses of host tables) and target-dependent entries for each target. Its format may be like this: void *__OPENMP_TARGET__[] = { _omp_host_func_table; _omp_host_funcs_end; _omp_host_var_table; _omp_host_vars_end; _omp_num_targets; _omp_target_descs[]; /* array of tgt_desc */ } struct tgt_desc { int _omp_tgt_id; void *_omp_tgt_%s_image_start; void *_omp_tgt_%s_image_end; void *_omp_tgt_%s_func_mappings; void *_omp_tgt_%s_var_mappings; /* some other data if needed */ } The mkoffload tool will fill those symbols, that are required by the corresponding target. E.g. for the MIC and PTX targets the openmp_target descriptor will look like: { &_omp_host_func_table, &_omp_host_funcs_end, &_omp_host_var_table, &_omp_host_vars_end, 2, MIC_ID, &_omp_tgt_mic_image_start, &_omp_tgt_mic_image_end, &_omp_tgt_mic_func_mappings, /* 0 */ &_omp_tgt_mic_var_mappings, /* 0 */ PTX_ID, &_omp_tgt_ptx_image_start, &_omp_tgt_ptx_image_end, /* 0 */ &_omp_tgt_ptx_func_mappings, &_omp_tgt_ptx_var_mappings } During the devices initialization libgomp will pass the openmp_target pointer to all plugins. Each plugin will scan over tgt_descs and find the required entries using the _omp_tgt_id. Then the plugin loads the image to the target, does whatever it wants, and returns func_mappings and var_mappings to libgomp, because libgomp has to add host-target mapping into the splay tree. How does this look? BTW, do you have any estimate when you will commit your patches to the branch, so that we could merge them with ours, and get something working for everybody? -- Ilya
On 03/05/2014 06:15 PM, Ilya Verbin wrote: > On 28 Feb 17:21, Bernd Schmidt wrote: >> I think it won't help that much - I still think this entire scheme >> is likely to fail on nvptx. I'll try to construct an example at >> some point. >> >> One other thing about the split tables is that we don't have to >> write a useless size of 1 for functions. >> >> >> The concept of "image" is likely to vary somewhat between >> accelerators. For ptx, it's just a string and it can't really be >> generated the same way as for your target where you can manipulate >> ELF images. So I think it is better to have a call to a gomp >> registration function for every offload target. That should also >> give you the ordering you said you wanted between shared >> libraries. >> >> >> Probably. I think the constructor call to the gomp registration >> function would contain an opaque pointer to whatever data the >> target wants, so it can arrange its image/table data in whatever >> way it likes. > > Assuming that we're using the scheme with tables. Every DSO with > offloading must contain a constructor call to GOMP_offload_register > (const void *openmp_target); The openmp_target descriptor in every > DSO will have target-independent entries (addresses of host tables) > and target-dependent entries for each target. Its format may be like > this: > > void *__OPENMP_TARGET__[] = { _omp_host_func_table; > _omp_host_funcs_end; _omp_host_var_table; _omp_host_vars_end; > _omp_num_targets; _omp_target_descs[]; /* array of tgt_desc */ } I don't see why you want the array of target descriptors - it would take some effort to construct, and as far as I can tell it's unnecessary. You can just pass a pointer to the corresponding descriptor to every GOMP_offload_register call. > struct tgt_desc { int _omp_tgt_id; void *_omp_tgt_%s_image_start; > void *_omp_tgt_%s_image_end; void *_omp_tgt_%s_func_mappings; void > *_omp_tgt_%s_var_mappings; /* some other data if needed */ } This looks reasonable. > During the devices initialization libgomp will pass the openmp_target > pointer to all plugins. Each plugin will scan over tgt_descs and find > the required entries using the _omp_tgt_id. Once again, that seems unnecessarily complicated. The plugins can register their target ID with libgomp, and when libgomp sees a GOMP_offload_register call with the corresponding target ID, it can invoke the appropriate plugin immediately. > BTW, do you have any estimate when you will commit your patches to > the branch, so that we could merge them with ours, and get something > working for everybody? I've been waiting for us to reach agreement on how things should look. If there are patches in the series that you're happy with, let me know and I can commit them (it may be next week though). Bernd
2014-03-06 12:47 GMT+04:00 Bernd Schmidt <bernds@codesourcery.com>: > I don't see why you want the array of target descriptors - it would take > some effort to construct, and as far as I can tell it's unnecessary. You > can just pass a pointer to the corresponding descriptor to every > GOMP_offload_register call. > > Once again, that seems unnecessarily complicated. The plugins can register > their target ID with libgomp, and when libgomp sees a GOMP_offload_register > call with the corresponding target ID, it can invoke the appropriate plugin > immediately. Do I understand correctly, that you propose to do so: extern void *_omp_host_func_table[]; extern void *_omp_host_var_table[]; extern void *_omp_host_funcs_end[]; extern void *_omp_host_vars_end[]; void *__OPENMP_TARGET_HOST__[] __attribute__ ((visibility ("protected"))) = { &_omp_host_func_table, &_omp_host_funcs_end, &_omp_host_var_table, &_omp_host_vars_end }; extern void *__OPENMP_TARGET_MIC__[]; extern void *__OPENMP_TARGET_PTX__[]; extern void GOMP_offload_register_host (const void *); extern void GOMP_offload_register_target (const void *); __attribute__ ((constructor)) static void init (void) { GOMP_offload_register_host (__OPENMP_TARGET_HOST__); GOMP_offload_register_target (__OPENMP_TARGET_MIC__); GOMP_offload_register_target (__OPENMP_TARGET_PTX__); } Where __OPENMP_TARGET_MIC__ and __OPENMP_TARGET_PTX__ descriptors should be generated in the corresponding mkoffload tools. -- Ilya
On 03/06/2014 12:11 PM, Ilya Verbin wrote: > Do I understand correctly, that you propose to do so: > > extern void *_omp_host_func_table[]; > extern void *_omp_host_var_table[]; > extern void *_omp_host_funcs_end[]; > extern void *_omp_host_vars_end[]; > > void *__OPENMP_TARGET_HOST__[] > __attribute__ ((visibility ("protected"))) = > { > &_omp_host_func_table, &_omp_host_funcs_end, > &_omp_host_var_table, &_omp_host_vars_end > }; So far, yes (maybe just call it __OPENMP_HOST_TABLE__). > extern void *__OPENMP_TARGET_MIC__[]; > extern void *__OPENMP_TARGET_PTX__[]; > extern void GOMP_offload_register_host (const void *); > extern void GOMP_offload_register_target (const void *); > > __attribute__ ((constructor)) > static void > init (void) > { > GOMP_offload_register_host (__OPENMP_TARGET_HOST__); > GOMP_offload_register_target (__OPENMP_TARGET_MIC__); > GOMP_offload_register_target (__OPENMP_TARGET_PTX__); > } > > Where __OPENMP_TARGET_MIC__ and __OPENMP_TARGET_PTX__ descriptors > should be generated in the corresponding mkoffload tools. No. I don't think we need a global constructor for registering __OPENMP_TARGET_HOST__ - this would unnecessarily bloat crtbegin/crtend. We also shouldn't need to have the target tables known outside of the image constructed by the mkoffload tools. The way I imagine it, every mkoffload tool creates its own constructor that looks like something like this: __attribute__ ((constructor)) static void init (void) { GOMP_offload_register_target (__OPENMP_TARGET_HOST__, PTX_ID, ptx_target_table); } That creates a mapping between host and target table for PTX_ID. If there are multiple shared libraries with offload support, you can still obtain the ordering you want from these GOMP_offload_register_target calls. Everything is nicely private to the mkoffload-generated image. It's implemented in almost this fashion (slightly different naming and args, and no real support in libgomp) in the patch kit I sent. Bernd
2014-03-06 15:53 GMT+04:00 Bernd Schmidt <bernds@codesourcery.com>: > No. I don't think we need a global constructor for registering > __OPENMP_TARGET_HOST__ - this would unnecessarily bloat crtbegin/crtend. We > also shouldn't need to have the target tables known outside of the image > constructed by the mkoffload tools. The way I imagine it, every mkoffload > tool creates its own constructor that looks like something like this: > > > __attribute__ ((constructor)) static void > init (void) > { > GOMP_offload_register_target (__OPENMP_TARGET_HOST__, > PTX_ID, ptx_target_table); > } > > That creates a mapping between host and target table for PTX_ID. If there > are multiple shared libraries with offload support, you can still obtain the > ordering you want from these GOMP_offload_register_target calls. Everything > is nicely private to the mkoffload-generated image. > > It's implemented in almost this fashion (slightly different naming and args, > and no real support in libgomp) in the patch kit I sent. OK, now I get it, this looks good. I will rewrite the patch for libgomp posted above to support this scheme. Since we will pass __OPENMP_HOST_TABLE__ to GOMP_offload_register, there is no need to pass it to GOMP_target[data/update], right? -- Ilya
Hello Bernd, On 28 Feb 17:21, Bernd Schmidt wrote: > For your use case, I'd imagine the offload compiler would be built > relatively normally as a full build with > "--enable-as-accelerator-for=x86_64-linux", which would install it > into locations where the host will eventually be able to find it. > Then the host compiler would be built with another new configure > option (as yet unimplemented in my patch set) > "--enable-offload-targets=mic,..." which would tell the host > compiler about the pre-built offload target compilers. On the ptx I don't get this part of the plan. Where a host compiler will look for mkoffloads? E.g., first I configure/make/install the target gcc and corresponding mkoffload with the following options: --enable-accelerator=intelmic --enable-as-accelerator-for=x86_64-unknown-linux --prefix=/install_gcc/accel_intelmic Next I configure/make/install the host gcc with: --enable-accelerator=intelmic --prefix=/install_gcc/host Now if I manually copy mkoffload from target's install dir into one of the dirs in host's $COMPILER_PATH, then lto-wrapper finds it and everything works fine. E.g.: mkdir -p /install_gcc/host/libexec/gcc/x86_64-unknown-linux-gnu/accel/intelmic/ && cp /install_gcc/accel_intelmic/libexec/gcc/x86_64-unknown-linux/4.10.0/accel/x86_64-unknown-linux-gnu/mkoffload /install_gcc/host/libexec/gcc/x86_64-unknown-linux-gnu/accel/intelmic/ But what was your idea of how to tell host gcc about the path to mkoffload? Thanks, -- Ilya
On 06/17/2014 08:20 PM, Ilya Verbin wrote: > Hello Bernd, > > On 28 Feb 17:21, Bernd Schmidt wrote: >> For your use case, I'd imagine the offload compiler would be built >> relatively normally as a full build with >> "--enable-as-accelerator-for=x86_64-linux", which would install it >> into locations where the host will eventually be able to find it. >> Then the host compiler would be built with another new configure >> option (as yet unimplemented in my patch set) >> "--enable-offload-targets=mic,..." which would tell the host >> compiler about the pre-built offload target compilers. On the ptx > > I don't get this part of the plan. Where a host compiler will look for mkoffloads? > > E.g., first I configure/make/install the target gcc and corresponding mkoffload with the following options: > --enable-accelerator=intelmic --enable-as-accelerator-for=x86_64-unknown-linux --prefix=/install_gcc/accel_intelmic > > Next I configure/make/install the host gcc with: > --enable-accelerator=intelmic --prefix=/install_gcc/host Try using the same prefix for both. Bernd
On 17 Jun 21:22, Bernd Schmidt wrote: > On 06/17/2014 08:20 PM, Ilya Verbin wrote: > >I don't get this part of the plan. Where a host compiler will look for mkoffloads? > > > >E.g., first I configure/make/install the target gcc and corresponding mkoffload with the following options: > >--enable-accelerator=intelmic --enable-as-accelerator-for=x86_64-unknown-linux --prefix=/install_gcc/accel_intelmic > > > >Next I configure/make/install the host gcc with: > >--enable-accelerator=intelmic --prefix=/install_gcc/host > > Try using the same prefix for both. I tried to do: 1. --enable-accelerator=intelmic --enable-as-accelerator-for=x86_64-intelmic-linux-gnu --prefix=/install_gcc/both 2. --enable-accelerator=intelmic --prefix=/install_gcc/both In this case only bin/x86_64-intelmic-linux-gnu-accel-intelmic-gcc from accel compiler is saved. All other binaries in bin, lib, lib64, libexec are replaced by host's ones. Is there a way to have 2 working compilers and libs in the same prefix? Thanks, -- Ilya
On 06/18/2014 04:13 PM, Ilya Verbin wrote: > On 17 Jun 21:22, Bernd Schmidt wrote: >> On 06/17/2014 08:20 PM, Ilya Verbin wrote: >>> I don't get this part of the plan. Where a host compiler will look for mkoffloads? >>> >>> E.g., first I configure/make/install the target gcc and corresponding mkoffload with the following options: >>> --enable-accelerator=intelmic --enable-as-accelerator-for=x86_64-unknown-linux --prefix=/install_gcc/accel_intelmic >>> >>> Next I configure/make/install the host gcc with: >>> --enable-accelerator=intelmic --prefix=/install_gcc/host >> >> Try using the same prefix for both. > > I tried to do: > 1. --enable-accelerator=intelmic --enable-as-accelerator-for=x86_64-intelmic-linux-gnu --prefix=/install_gcc/both > 2. --enable-accelerator=intelmic --prefix=/install_gcc/both > > In this case only bin/x86_64-intelmic-linux-gnu-accel-intelmic-gcc from accel compiler is saved. > All other binaries in bin, lib, lib64, libexec are replaced by host's ones. > Is there a way to have 2 working compilers and libs in the same prefix? Sure, as long as the target triplet is different. What I think you need to do is For the first compiler: --enable-as-accelerator-for=x86_64-pc-linux-gnu --target=x86_64-intelmic-linux-gnu --prefix=/somewhere Build and install, then: For the second: configure --enable-offload-targets=x86_64-intelmic-linux-gnu x86_64-pc-linux-gnu --prefix=/somewhere No --enable-accelerator options at all. This should work, if it doesn't let me know what you find in /somewhere after installation for both compilers. Bernd
On 18 Jun 16:22, Bernd Schmidt wrote: > What I think you need to do is > For the first compiler: > --enable-as-accelerator-for=x86_64-pc-linux-gnu > --target=x86_64-intelmic-linux-gnu --prefix=/somewhere > > No --enable-accelerator options at all. This should work, if it > doesn't let me know what you find in /somewhere after installation > for both compilers. It doesn't work without --enable-accelerator: --enable-as-accelerator-for requires --enable-accelerator make[1]: *** [configure-gcc] Error 1 -- Ilya
Index: libgomp/libgomp.map =================================================================== --- libgomp/libgomp.map (revision 207857) +++ libgomp/libgomp.map (working copy) @@ -226,6 +226,7 @@ GOMP_4.0 { GOMP_target_end_data; GOMP_target_update; GOMP_teams; + GOMP_offload_register; } GOMP_3.0; OACC_2.0 { Index: libgomp/libgomp_g.h =================================================================== --- libgomp/libgomp_g.h (revision 207857) +++ libgomp/libgomp_g.h (working copy) @@ -213,7 +213,8 @@ extern void GOMP_target_end_data (void); extern void GOMP_target_update (int, const void *, size_t, void **, size_t *, unsigned char *); extern void GOMP_teams (unsigned int, unsigned int); - +extern void GOMP_offload_register (const void *, const char *, + const void *, const void *, void *); /* oacc-parallel.c */ extern void GOACC_parallel (int, void (*) (void *), const void *, Index: libgomp/target.c =================================================================== --- libgomp/target.c (revision 207857) +++ libgomp/target.c (working copy) @@ -714,6 +714,13 @@ gomp_target_init (void) gomp_find_available_plugins (); } +void +GOMP_offload_register (const void *target_id, const char *target_name, + const void *func_mappings, const void *var_mappings, + void *target_data) +{ +} + #else /* PLUGIN_SUPPORT */ /* If dlfcn.h is unavailable we always fallback to host execution. GOMP_target* routines are just stubs for this case. */