Blair,
> I'm writing an application that requires an Action to be parameterised by
> a user provided function, in the style of Cole's algorithmic skeletons.
>
> Currently the user provides these functions as Action types (since we need
> to be able to serialise them and we can use them as template params).
> Something along the lines of:
>
> HPX_PLAIN_ACTION(userFn, userFn_act)
> HPX_PLAIN_ACTION(skeleton<userFn_act>, skeleton_act)
>
> Essentially giving us a new type that "captures" the user provided
> function.
>
> Unfortunately for the application (recursive tree search, with several
> million calls to the function), calling userFn as an action slows things
> down significantly (additional allocations and synchronisation overhead).
It's mainly the need to find out whether the id_type used refers to a local or
a remote entity which introduces the overheads you're seeing.
> Even defining it as a direct action still seems to add additional
> synchronisation.
>
> Ideally, for performance, I'd like to get the raw function pointer back
> once I call "skeleton" on a possibly remote node. Something like:
>
> fastTask(userFnType & fn);
>
> template<userFn>
> skeletonTask() {
>
> userFn fn;
> fastTask(fn.getRawPointer());
>
> }
>
> Does such a method exist? Or am I looking at this in the wrong manner? Is
> there a better way to serialise raw function pointers without using the
> Action interface? I know that it is only ever "skeleton" that will be
> called in an async.
If there was a way to serialize plain function pointers we didn't need to
introduce actions in the first place ;-)
But jokes apart... IIUC, you'd like to invoke 'userFn' if given a 'userFn_act'.
This can be achieved by calling the (static) member function of actions called
invoke:
template <typename Action, typename ... Ts>
auto invoke_underlying_function(Ts &&... ts)
{
return Action::invoke(<addr>, std::forward<Ts>(ts)...);
}
And then use it as:
auto r = invoke_underlying_function<userFc_act>(...);
Here the only tricky part is to find the correct value for <addr>. For global
functions (plain actions) this value is ignored, so it can be 0 (zero). For
component actions this has to be the 'this' pointer of the object the (member-)
function (bound to the component action) should be invoked for (see also [1]
and [2]).
HTH
Regards Hartmut
---------------
http://boost-spirit.com
http://stellar.cct.lsu.edu
[1]
https://github.com/STEllAR-GROUP/hpx/blob/master/hpx/runtime/actions/plain_action.hpp#L74-L80
[2]
https://github.com/STEllAR-GROUP/hpx/blob/master/hpx/runtime/actions/component_action.hpp#L58-L65
_______________________________________________
hpx-users mailing list
[email protected]
https://mail.cct.lsu.edu/mailman/listinfo/hpx-users