• Parallelism: Multiple computations are done simultaneously.
• Instruction level (pipelining)
• Data parallelism (SIMD)
• Task parallelism (embarrassinglyparallel)
• Concurrency: Multiple computations that may be done inparallel.
• Concurrency vs. Parallelism
concurrency和parallelism是不同的,可以参考这篇英文文章。拿两个简单的计算任务T1和T2为例,简单地说,concurrency指T1与T2的执行顺序可以不确定,而parallelism指T1和T2可以同时在多个CPU上运算。
• Process: An instance of a program that is being executed inits own address space. In POSIX systems, each process maintains itsown heap, stack, registers, file descriptors etc.
Communication:
• Shared memory
• Network
• Pipes, Queues
• Thread: A light weight process that shares its address spacewith others.In POSIX systems, each thread maintains the bareessentials: registers, stack, signals.
Communication:
• shared address space.
线程必须有自己的栈,因为线程的执行顺序不是线性的,如果用进程栈的话就会导致混乱。线程不需要自己的堆和文件描述符,我想是因为相对而言堆是静态的,即不会用堆的结构来控制程序的执行结构。文件描述符是将文件映射到进程的虚拟内存中所做的标记,因此也是全局性质的。
Serial execution:
• All our programs so far has had asingle thread of execution: main thread.
• Program exits when the mainthread exits.
Multithreaded:
• Program is organized as multipleand concurrent threads of execution.
• The main thread spawns multiplethreads.
• The thread may communicate withone another.
• Advantages:
• Improves performance
• Improves responsiveness
• Improves utilization
• less overhead compared to multipleprocesses
多线程的程序最大的好处就是使不同类型的线程交叉运行,利用人类与机器的巨大速度差异,使人有一种程序并发执行的假象。这个在图形用户界面中和数据的读取中使用的最为成功,其实也就是MVC中的M和V。现在想想,世界上很多东西都有一种神奇的联系,就像数学和机器,艺术和数学等。
使用进程来协作完成一件任务,虽然可以使内存获得更有效的保护(独立的虚拟内存),但同时也存在着这些缺点:1.进程之间的切换代价较高;2.操作系统可以有效控制的进程数是有限的;3.多进程共享的数据在同步代价较大。
Even in C, multithread programming may be accomplished in severalways
• Pthreads: POSIX C library.
• OpenMP
• Intel threading building blocks
• Cilk (from CSAIL!)
• Grand central despatch
• CUDA (GPU)
• OpenCL (GPU/CPU)
学习曲线似乎是一个比一个高,我正打算学OpenMP,听说比较好上手且效率提升效果还行。
右侧的循环不能并行化是因为存在数据依赖,我称之为数据递归。存在强依赖的递归程序(也就是咱们平时所说的递归程序)很难实现并行化。
API:
• Threadmanagement: creating, joining, attributes
pthread_
• Mutexes:create, destroy mutexes
pthread_mutex_
• Conditionvariables: create,destroy,wait,signal
pthread_cond_
• Synchronization:read/write locks and barriers
pthread_rwlock_,pthread_barrier_
API:
• #include<pthread.h>
• gcc−Wall −O0 −o <output> file.c −pthread (no −l prefix)
Pthread主要使用锁来控制并发,跟数据库有些类似,这些锁主要有互斥锁,条件锁等。
int pthread_create(pthread_t∗thread, const pthread_attr_t ∗ attr, void ∗(∗start_routine)(void ∗), void ∗ arg);
• creates a new thread with theattributes specified by attr.
• Default attributes are used ifattr is NULL.
• On success, stores the thread itinto thread
• calls function start_routine(arg)on a separatethread of execution.
• returns zero on success, non-zeroon error.
void pthread_exit(void∗value_ptr);
• called implicitly when threadfunction exits.
• analogous to exit().
线程中的方法参数和返回值为什么都void类型呢?参数很耗理解,因为只有void可以方便地转换为其它类型。返回值是void,也就是没有返回值,我想是因为每个线程都是相对独立的,他们通过共享内存(堆?)来进行通信,而且其程序运行在自己的栈中,因此不需要也不能通过返回值进行通信。Thread的停止条件有这几个:1.调用pthread_exit;2.start_routine返回;3.线程被取消pthread_cancel;
int pthread_join(pthread_tthread, void ∗∗value_ptr);
• pthread_join() blocks the callingthread until the specified thread terminates.
• If value_ptr is not null, it willcontain the return status of the called thread
Other ways to synchronize: mutex,condition variables
如果线程T1 join线程T2,那么T1将等待T2结束后才开始执行。线程是先创建然后再设置join,因此需要将attr设置为PTHREAD_CREATE_JOINABLE,防止线程在创建时就运行。
• Mutex (mutual exclusion) acts as a "lock" protectingaccess to the shared resource.
• Only one thread can "own" the mutex at a time.Threads must take turns to lock the mutex.
intpthread_mutex_destroy(pthread_mutex_t ∗mutex);
intpthread_mutex_init(pthread_mutex_t ∗ mutex, constpthread_mutexattr_t ∗ attr);
thread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ;
• pthread_mutex_init() initializes a mutex. If attributes areNULL, default attributes are used.
• The macro PTHREAD_MUTEX_INITIALIZER can be used to initializestatic mutexes.
• pthread_mutex_destroy() destroys the mutex.
• Both function return return 0 on success, non zero on error
intpthread_mutex_lock(pthread_mutex_t ∗mutex);
intpthread_mutex_trylock(pthread_mutex_t∗mutex);
intpthread_mutex_unlock(pthread_mutex_t ∗mutex);
• pthread_mutex_lock() locks the given mutex. If the mutex islocked, the function is blocked until it becomes available.
• pthread_mutex_trylock() is the non-blocking version. If themutex is currently locked the call will return immediately.
• pthread_mutex_unlock() unlocks the mutex.
互斥锁感觉没什么好说的,相关的原理在数据库系统原理里面讲了很多。不知为什么,我不是很喜欢这种方法,总感觉很复杂。
Sometimes locking or unlocking is based on a run-time condition(examples?).Without condition variables, program would have to pollthe variable/condition continuously.
Consumer:
(a) lock mutex on global itemvariable
(b) wait for (item>0) signal fromproducer (mutex unlocked automatically).
(c) wake up when signalled (mutexlocked again automatically), unlock mutex and proceed.
Producer:
(1) produce something
(2) Lock global item variable, updateitem
(3) signal waiting (threads)
(4) unlock mutex
intpthread_cond_wait(pthread_cond_t ∗cond, pthread_mutex_t ∗mutex);
• blocks on a condition variable.
• must be called with the mutexalready locked otherwise behavior undefined.
• automatically releases mutex
• upon successful return, the mutexwill be automatically locked again.
intpthread_cond_broadcast(pthread_cond_t ∗cond);
intpthread_cond_signal(pthread_cond_t ∗cond);
• unblocks threads waiting on acondition variable.
• pthread_cond_broadcast() unlocksall threads that are waiting.
• pthread_cond_signal() unlocks oneof the threads that are waiting.
• both return 0 on success, non zerootherwise.
和MFC中的文档试—视图结构很类似,也是I/O中比较常见的一种情况。感觉这个像是mutex的一种应用模式。