Skip to content
This repository has been archived by the owner on Mar 3, 2020. It is now read-only.

LibraryInstanceGeneration

Stefan Vigerske edited this page Mar 3, 2020 · 1 revision

PFunc offers a wide variety customizations to its users without incurring any runtime penalties. The first step in using PFunc is to generate a customized library instance description that best suits their needs (C++ only). Then, the generated library instance description is used to parallelize user applications. The customizable features provided by PFunc are:

  • Scheduling policy: The value provided to this feature determines the scheduling policy that is used in the generated library instance description. PFunc provides cilkS, prioS, lifoS and fifoS scheduling policies implicitly. PFunc's users can also define custom scheduling polices and use them as the value of this feature at instance generation time.

  • Compare: This feature represents the ordering function for task priorities and is used only if the chosen scheduling policy requires task priorities (prioS). PFunc also allows customization of the priority feature as it is inherited from the compare feature.

  • Function object: This feature allows users to specify the type of the function object that is executed by the tasks. By allowing the type of the function object to be specified as a feature, PFunc successfully avoids paying the cost of virtual function calls in the spawned tasks. This is true only when there is one function object that needs to be parallelized. In general, virtual function call cannot be avoided if more than one type of function objects needs to be parallelized. This is unlike other library-based approaches such as Intel's Threading Building Blocks, where spawning a new task involves a virtual function call.

C++

In C++, the required library instance description can be generated using template parameters to PFunc's generator interface. For example, consider the following piece of code:

typedef pfunc::generator<cilkS, /* scheduling policy */
                         pfunc::use_default, /* compare */
                         pfunc::use_default> my_pfunc; /*function object*/

Here, we have generated an new library instance description of PFunc by choosing the Cilk-style scheduling policy. The values for the compare and function object features are allowed to be defaults. It is possible to use pfunc::use_default for all the features. PFunc automatically chooses sensible values for the features in this case. The type my_pfunc thus generated in our example is a custom instance that can be used to parallelize user applications. In PFunc, there are four important types that users are exposed to. These are: _attribute, group, task and _taskmgr''. Once the required library instance description has been generated, these types can be accessed as follows:

my_pfunc::attribute attribute; 
my_pfunc::group group; 
my_pfunc::task task; 
my_pfunc::taskmgr taskmgr; 

Objects of type attribute allow users to control the execution of spawned tasks by setting attributes such as task priority and task affinity (see [wiki:TaskAttributes]). Objects of type group can be used to create collaborations of tasks that can communicate with each other using point-to-point message passing and barrier synchronization (see [wiki:TaskGroups]). Objects of type task are used as references to spawned tasks, which can be passed to other tasks. The ability to pass task references is crucial for the support of multiple task completion notifications (see [wiki:SpawnTasks]). Finally, objects of type taskmgr manage threads and their task queues, and are responsible for task scheduling.

C

In C, both because of the lack of support for generic programming and the pitfalls of over-using preprocessor macros, PFunc pre-generates the library instance descriptions for the users. The users are merely required to then select the right library instance description from the available set of pre-generated descriptions. The currently available library instance descriptions for C programmers are:

Instance description Scheduling policy Compare, priority Function type
pfunc_cilk*_ Cilk-style unused void ()(void)
pfunc_lifo*_ Stack-based unused void ()(void)
pfunc_fifo*_ Queue-based unused void ()(void)
pfunc_prio*_ Priority-based int, < op void ()(void)

The above table describes the four library instance descriptions that are available to the C programmers. Like in C++, there are four important types: attribute, group, task and taskmgr, which are exposed to the users. For example, consider the Cilk-style library instance description. The names by which these types can be accessed for the Cilk-style instance description are pfunc_cilk_attr_t, pfunc_cilk_group_t, pfunc_cilk_task_t and pfunc_cilk_taskmgr_t.

Caveat As PFunc is implemented completely in C++, the C types are mere typed pointers to their C++ counterparts. Consequently, before using these types (eg.,pfunc_cilk_attr_t, pfunc_cilk_group_t, etc), they need to be initialized and cleared explicitly using calls to their respective init and clear functions. This notion of initializing and clearing PFunc's C types will be reinforced throughout the C examples described in this tutorial.