Introduction to pThread
- pThread 頭文件:pthread.h
- Functions:
- pthread_mutex_unlock: 解除鎖定mutex所指向的互斥鎖的函數(shù)
- pthread_mutex_lock: 鎖定互斥鎖
- pthread_mutex_t: creat a mutex in pthread
- pthread_join: join with a terminated thread
- pthread_create: 創(chuàng)建thread
pthread_create(pthread_t tidp,const pthread_attr_t attr,(void)(start_rtn)(void*),void *arg);
arguments: 線程id工闺,線程屬性(就NULL吧),線程運(yùn)行函數(shù)地址瓣蛀,運(yùn)行函數(shù)參數(shù) - pthread_t: 定義thread id
- pthread_setaffinity_np: set the CPU affinity mask of a thread to the pointed CPU or CPUs
- pthread_getaffinity_np: return the CPU affinity mask of the thread in the buffer
Configuration
可以用lscpu顯示CPU configuration
Compile
pthread library已經(jīng)預(yù)裝在ubuntu
舉個(gè)例子:helloworld.c
#include <stdio.h>
#include <pthread.h>
void * hello(void *input) {
printf("%s\n", (char *)input);
pthread_exit(NULL);
}
int main(void) {
pthread_t tid;
pthread_create(&tid, NULL, hello, "hello world");
pthread_join(tid, NULL);
return 0;
}
Compile用
gcc -o helloworld helloworld.c -lpthread
運(yùn)行
./helloworld
Race Condition(競(jìng)爭(zhēng)條件)
source: https://blog.csdn.net/u012562273/article/details/56486776
(Oct 15 2018)
從多進(jìn)程間通信的角度來(lái)講陆蟆,是指兩個(gè)或多個(gè)進(jìn)程對(duì)共享的數(shù)據(jù)進(jìn)行讀或?qū)懙牟僮鲿r(shí),最終的結(jié)果取決于這些進(jìn)程的執(zhí)行順序惋增。(https://baike.baidu.com/item/%E7%AB%9E%E6%80%81%E6%9D%A1%E4%BB%B6/1321097?fr=aladdin)
Race Condition分為兩類
- Mutex(互斥): 兩個(gè)或多個(gè)進(jìn)程彼此之間沒(méi)有內(nèi)在的制約關(guān)系叠殷,但是由于要搶占使用某個(gè)臨界資源(不能被多個(gè)進(jìn)程同時(shí)使用的資源,如打印機(jī)诈皿,變量)而產(chǎn)生制約關(guān)系
- Synchonization(同步): 兩個(gè)或多個(gè)進(jìn)程彼此之間存在制約關(guān)系(前一個(gè)進(jìn)程執(zhí)行完林束,其他的進(jìn)程才能執(zhí)行)
Solutions
- Busy Waiting(忙等待): 等著但是不停的檢查測(cè)試,直到能進(jìn)行為止
- Sleep and Wakeup(睡眠與喚醒): 引入Semaphore稽亏,喚醒由其他進(jìn)程引發(fā)
舉個(gè)例子:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NITERS 10000000
void *count (void *arg);
unsigned int cnt = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int main () {
pthread_t tid1, tid2;
pthread_create (&tid1, NULL, count, NULL);
pthread_create (&tid2, NULL, count, NULL);
pthread_join (tid1, NULL);
pthread_join (tid2, NULL);
printf ("cnt:%d\n", cnt);
exit (0);
}
void *count (void *arg) {
int i = 0;
for (; i < NITERS; i++) {
pthread_mutex_lock(&mutex); //mutex
cnt++;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
Deadlock
e.g.
Allen borrows Book1 first, after the borrowes Book1, he starts to find Book2
Bob borrows Book2 first, after he borrowed Book2, he starts to find Book1.
-->Deadlock
Solution:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
void *Allen(void *arg);
void *Bob(void *arg);
pthread_mutex_t book1;
pthread_mutex_t book2;
pthread_cond_t Allenfinish;
int main() {
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, &Allen, NULL);
pthread_create(&tid2, NULL, &Bob, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
void *Allen(void *arg) {
pthread_mutex_lock(&book1);
sleep(5);
pthread_mutex_lock(&book2);
printf("Allen has collected all books he need, he is going to do homework!\n");
sleep(5);
printf("Allen has finished his homework, he has returned all books he borrowed!\n");
pthread_mutex_unlock(&book2);
pthread_mutex_unlock(&book1);
pthread_cond_signal(&Allenfinish);
}
void *Bob(void *arg) {
pthread_mutex_lock(&book2);
pthread_cond_wait(&Allenfinish, &book2);
printf("Bob knows he can borrow those two books now!\n");
pthread_mutex_lock(&book1);
sleep(5);
printf("Bob has finished his homework now!\n");
pthread_mutex_unlock(&book1);
pthread_mutex_unlock(&book2);
}
Passing Arguments
舉個(gè)栗子:
#include <stdio.h>
#include <pthread.h>
void * hello(void *input) {
printf("%s\n", (char *)input);
pthread_exit(NULL);
}
int main(void) {
pthread_t tid;
pthread_create(&tid, NULL, hello, "hello world");
pthread_join(tid, NULL);
return 0;
}
傳遞多個(gè)參數(shù):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct args {
char* name;
int age;
};
void *hello(void *input) {
printf("name: %s\n", ((struct args*)input)->name);
printf("age: %d\n", ((struct args*)input)->age);
}
int main() {
struct args *Allen = (struct args *)malloc(sizeof(struct args));
char allen[] = "Allen";
Allen->name = allen;
Allen->age = 20;
pthread_t tid;
pthread_create(&tid, NULL, hello, (void *)Allen);
pthread_join(tid, NULL);
return 0;
}
Pin a thread to a core
source: https://www.cnblogs.com/wenqiang/p/6049978.html
(Oct 15 2018)
Affinity
CPU的親和性(Affinity)就是將指定的進(jìn)程或線程綁定到相應(yīng)的CPU上
- 軟親和性:進(jìn)程在指定的CPU上盡量長(zhǎng)時(shí)間地運(yùn)行而不被遷移到其他處理器壶冒。linux內(nèi)核進(jìn)程調(diào)度器具有軟CPU親和性,不會(huì)再處理器之間頻繁遷移截歉,產(chǎn)生的負(fù)載小
- 硬親和性:利用linux內(nèi)核提供給用戶的API胖腾,強(qiáng)行將進(jìn)程綁定到指定的CPU運(yùn)行
相關(guān)functions
作者:jsdchenye
來(lái)源:CSDN
原文:https://blog.csdn.net/jsdchenye/article/details/44703615?utm_source=copy
- void CPU_ZERO(cpu_set_t *set);(初始化操作)
- void CPU_SET(int cpu,cpu_set_t *set)(將某個(gè)cpu加進(jìn)cpu集里)
- void CPU_CLR(int cpu,cpu_set_t *set)(將某個(gè)cpu清除出cpu集里)
- void CPU_ISSET(int cpu,const cpu_set_t *set)(判斷某個(gè)cpu是不是在cpu集里)
栗子:
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
/* print the error message and exit */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
int s, j;
int CPUNUM = 4;
cpu_set_t cpuset;
pthread_t thread;
thread = pthread_self(); // get the id of the current thread
CPU_ZERO(&cpuset); // empty the cpu set
for (j = 0; j < CPUNUM - 1; j++)
CPU_SET(j, &cpuset); // add each cpu to the cpu set except the cpu 3
/* Set affinity mask to include CPUs 0 to 2 */
s = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
if (s != 0)
handle_error_en(s, "pthread_setaffinity_np");
/* Check the actual affinity mask assigned to the thread */
s = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
if (s != 0)
handle_error_en(s, "pthread_getaffinity_np");
printf("Set returned by pthread_getaffinity_np() contained:\n");
for (j = 0; j < CPUNUM; j++)
if (CPU_ISSET(j, &cpuset))
printf("CPU %d is set affinity\n", j);
else
printf("CPU %d is not set affinity\n", j);
exit(EXIT_SUCCESS);
}
兩個(gè)栗子
source: https://www.cnblogs.com/wenqiang/p/6049978.html
(Oct 15 2018)
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
void *testfunc(void *arg)
{
int i, cpus = 0;
cpu_set_t mask;
cpu_set_t get;
cpus = sysconf(_SC_NPROCESSORS_CONF);
printf("this system has %d processor(s)\n", cpus);
CPU_ZERO(&mask);
for (i = 0; i < 4; i++) { /*將0、1瘪松、2咸作、3添加到集合中*/
CPU_SET(i, &mask);
}
/* 設(shè)置cpu 親和性(affinity)*/
if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
fprintf(stderr, "set thread affinity failed\n");
}
/* 查看cpu 親和性(affinity)*/
CPU_ZERO(&get);
if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
fprintf(stderr, "get thread affinity failed\n");
}
/* 查看當(dāng)前線程所運(yùn)行的所有cpu*/
for (i = 0; i < cpus; i++) {
if (CPU_ISSET(i, &get)) {
printf("this thread %d is running in processor %d\n", (int)pthread_self(), i);
}
}
sleep(3); //查看
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t tid;
if (pthread_create(&tid, NULL, (void *)testfunc, NULL) != 0) {
fprintf(stderr, "thread create failed\n");
return -1;
}
pthread_join(tid, NULL);
return 0;
}
Introduction to OpenMP
Hello, World!
栗子
#include <omp.h>
#include <stdio.h>
main(int argc, char *argv[]) {
int nthreads, tid;
/* Fork a team of threads with each thread having a private tid variable */
#pragma omp parallel private(tid)
{
/* Obtain and print thread id */
tid = omp_get_thread_num();
printf("Hello World from thread = %d\n", tid);
/* Only master thread does this */
if (tid == 0)
{
nthreads = omp_get_num_threads();
printf("Number of threads = %d\n", nthreads);
}
} /* All threads join master thread and terminate */
}
Compile:
gcc -o helloworld helloworld.c -fopenmp
To run:
./heloworld
Hello World from thread = 0
Number of threads = 4
Hello World from thread = 3
Hello World from thread = 2
Hello World from thread = 1
Parallel in OpenMP
#pragma omp parallel private(tid)
compiler directive statement, 寫在parallel region之前
omp_set_num_threads(4):
告訴compiler需要4個(gè)線程
pragma omp parallel for
告訴compiler將for loop并行
Getting faster using OpenMP
//他爸爸的太難了, 看不下去