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

Reply via email to