Note:
User Guide: http://software.intel.com/zh-cn/forums/showthread.php? T000077996&o=a&s=lr(cilk_user_guide.pdf)
This document provides some learning notes for this User Guide (Chinese version), simplifies the process, and gives you a better understanding of the code. You can refer to the original document for more details.
1. cilk_spawn
2. cilk_sync
3. cilk_for
4. predefine macro _ cilk
5. Environment Variable nworkers
1. cilk_spawn
The core of cilk is three keywords: _ cilk_spawn, _ cilk_sync and _ cilk_for. The header file <cilk/cilk. h> provides the macro definition of simplified keywords (cilk_spawn, cilk_sync, and cilk_for). Generally, simplified keywords are used in code.
The cilk_spawn keyword modifies the function call statement to inform the cilk to run the system. This function may (but is not required) be executed in parallel with the caller.
In a simple understanding, the Chinese translation of spawn is "derivative". This keyword indicates that the modified function may be executed in parallel with the currently executed code (strand, that is, "derivative" generates a new thread. We will discuss in detail the execution model of "derivative" and what you need to pay attention to later.
Three Forms of cilk_spawn:
Type Var = cilk_spawn func (ARGs); // func () returns cilk_spawn func (ARGs ); // No return value for func ()
The three forms are easy to understand. func is a function that is modified and may be executed in parallel with the current code. The three forms are exactly the same as the common function call forms, the keyword cilk_spawn is added for modification.
A derived function is called a subtask of the function that derives it. On the contrary, the function that executes the cilk_spawn statement is called the parent task of the derived function.
Derivative functions can use any function expression, but cannot use the cilk_spawn statement in the parameters of another function. For example:
Var = cilk_spawn (object. * pointer) (ARGs); // use a function pointer or a member function pointer
G (cilk_spawn F (); // No. The cilk_spawn statement is used for function parameters.
The solution is to derive a function to call f () and g (), for example, cilk_spawn [&] {G (f ());}(); (completed using the lambda expression of c ++)
Note: This method is different from cilk_spawn g (f (). In this way, F () is executed in the parent task before the derivative g (), and in the Lamda expression, both F () and g () are executed in subtasks.
2. cilk_sync
The cilk_sync statement indicates that the current function cannot be executed in parallel with derivative subtasks. After all sub-tasks are executed, the current function can continue to be executed.
Syntax: cilk_sync;
Note: Obviously, sync means "synchronization". In most parallel programming, there is such a concept. cilk_sync is a "wait" meaning, waiting for the current task (parent task) after the derivative subtasks are completed, they are executed.
Note that cilk_sync only synchronizes subtasks derived from this function. Subtasks of other functions are not affected. PS: This is actually obvious. It is easy to think of that if a derives B, B derives C, and sync in, it will certainly synchronize B. Will it wait for C? This is obvious, yes. Because each spawn function has an implicit sync at the end. If a will wait for B, C will certainly end before B ends.
Cilk_sync may exist implicitly in some cases. One of the implicit situations is that there is an implicit cilk_sync in each function that contains cilk_spawn and the end of the try block. The reason is as follows:
Make sure that the use of program resources does not exceed the parallel part of the program.
Make sure that non-competing parallel programs have the same behavior as the corresponding serial programs. A common non-derivative function call performs the same action no matter whether the called function is derived or not.
There is no possible side effect or the remaining strands that do not release resources continue to be executed.
The called function has completed all operations when it returns.
Example 1: understand the basic functions of cilk_spawn and cilk_sync, as follows:
// File: test1.cpp # include <stdio. h> # include <windows. h> # include <cilk/cilk. h> # define m10int m = 0, S = 0; int subtask () {for (INT I = 0; I <m/2; I ++) {printf ("this is sub task, I = % d, M = % d, S = % d \ n", I, m, S); sleep (1 );} return 1 ;}int maintask () {for (INT I = 0; I <m; I ++) {printf ("this is main task, I = % d, M = % d, S = % d \ n ", I, m, S); sleep (1);} return 1 ;}int main () {printf ("main strand started... \ n "); s = cilk_spawn subtask (); printf (" main task started... \ n "); M = maintask (); cilk_sync; // implicit return 0 ;}
Compilation: ICC test1.cpp
3. cilk_for
The cilk_for loop is used to replace the conventional C/C ++ for loop, which allows parallel execution of loop iterations. The format is the same as:
cilk_for (declaration; conditional expression; increment expression)body
Note: the serialization of cilk_for is the result of replacing cilk_for with. Therefore, a cilk_for loop must be a valid C/C ++ for loop, however, cilk_for loops have more restrictions than C/C ++ for loops (see the manual for more ).
Because the loop body must be executed in parallel, neither the scalar control nor the non-local variable can be modified. Otherwise, data competition will occur.
The content of cilk_for is complex. Reference manual and subsequent instructions.
4. pre-processor _ cilk
This macro is automatically defined by the compiler and set to the cilk Language extension version.
5. Environment Variable cilk_nworkers
Specifies the number of worker threads.