Here, it is important to not that for cilk_spawn, the caller may continue executing asynchronously with the execution of foo. This means it indicates something different than pthread_create, in which the compiler would create another execution context and run foo.
@ok agree. this is the power of abstraction.
Also, it reminds me of MS's async&await;. the difference is that await will yield the control back to the caller function when the task created is not finished and cilk_sync will suspend the program.
@ok. While I know what you mean, I'm going to jump in as the clarity police. Compilers don't create pthreads. The compiled code will certainly contain a call to the pthread_create function, whose implementation in the pthread runtime library will create another thread of execution (backed by a new execution context) and that thread will run foo.
I was still confused about the difference between cilk and pthreads and found some interesting answers in forums online.
Cilk is a parallel language, and multithreading and parallelism may not always mean the same thing. You could have multiple pthreads running on one core. A program using pthreads can call multiple threads on one core but a cilk program running on one core will not.
Also, spawning a pthread is hundreds of times slower than calling cilk_spawn. pthreads are thus better used for tasks that will run for a long time - to make up for the overhead.
I am still pretty confused about the differences between pthreads and a cilk program here. Primarily when we say that in the case of pthread_create a separate execution context is created, does that mean that there isn't one in the case of cilk spawn? So in that case are the instructions streams of the spawned function and the caller merged into one execution context where ILP can be exploited?
A pthread is at its core, a construct that the OS uses to schedule execution to different hardware contexts, so the OS is making scheduling decisions about its "tasks" (i.e., pthreads) to its execution resources (i.e., the hardware).
In Cilk, the Cilk runtime will be instructed to create tasks (i.e., cilk_spawn) and schedule these to its execution resources (i.e., its thread pool).
Notice that both systems are making scheduling decisions about "tasks" on its resources; however, a pthread's execution context is much larger than a Cilk execution context and the cost to switch hardware contexts is also higher.
So is Cilk an abstraction on top of pthreads (which is probably part of its implementation, but not necessarily directly cilk thread --> pthread)? If you use a Cilk logical thread, you don't specify whether there will be a new pthread/context or not, the Cilk runtime will decide that?
Just one minor nitpick with what @bpr said - a pthread is an abstraction over an OS task, not an OS task.
(woohoo, it's abstractions all the way down!)
It's fairly an inefficient way to abstract thread in kernel level, as pointed out by scheduler activation paper decades ago. And I think these ISPC or Cilk is trying to abstract the parallelism model which can be implemented easily in user space: the user-space thread benefits the performance advantage but suffers the correctness issue, the scheduler activation requires modification of kernel, thus abstract something over thread might seem most promising way to get both performance and correctness. Hopefully my understanding might help those in confusion of thread/Cilk/ISPC.
Comparing cilk_spawn with ISPC launch:
The launch perform SPMD instruction, all instance are executing the same program with different data.
The cilk_spawn is the higher level abstraction that doesn't have to spawn the same program.