Thread

作者: 白宇的斑马 | 来源:发表于2018-10-15 22:01 被阅读0次

Introduction to pThread

  • pThread 头文件:pthread.h
  • Functions:
  1. pthread_mutex_unlock: 解除锁定mutex所指向的互斥锁的函数
  2. pthread_mutex_lock: 锁定互斥锁
  3. pthread_mutex_t: creat a mutex in pthread
  4. pthread_join: join with a terminated thread
  5. pthread_create: 创建thread
    pthread_create(pthread_t tidp,const pthread_attr_t attr,(void)(start_rtn)(void*),void *arg);
    arguments: 线程id,线程属性(就NULL吧),线程运行函数地址,运行函数参数
  6. pthread_t: 定义thread id
  7. pthread_setaffinity_np: set the CPU affinity mask of a thread to the pointed CPU or CPUs
  8. pthread_getaffinity_np: return the CPU affinity mask of the thread in the buffer

Configuration

可以用lscpu显示CPU configuration

Compile

pthread library已经预装在ubuntu
举个例子: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
运行
./helloworld

Race Condition(竞争条件)

source: https://blog.csdn.net/u012562273/article/details/56486776
(Oct 15 2018)

从多进程间通信的角度来讲,是指两个或多个进程对共享的数据进行读或写的操作时,最终的结果取决于这些进程的执行顺序。(https://baike.baidu.com/item/%E7%AB%9E%E6%80%81%E6%9D%A1%E4%BB%B6/1321097?fr=aladdin)

Race Condition分为两类

  • Mutex(互斥): 两个或多个进程彼此之间没有内在的制约关系,但是由于要抢占使用某个临界资源(不能被多个进程同时使用的资源,如打印机,变量)而产生制约关系
  • Synchonization(同步): 两个或多个进程彼此之间存在制约关系(前一个进程执行完,其他的进程才能执行)

Solutions

  • Busy Waiting(忙等待): 等着但是不停的检查测试,直到能进行为止
  • Sleep and Wakeup(睡眠与唤醒): 引入Semaphore,唤醒由其他进程引发
    举个例子:
#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

举个栗子:

#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;
}

传递多个参数:

#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)就是将指定的进程或线程绑定到相应的CPU上

  • 软亲和性:进程在指定的CPU上尽量长时间地运行而不被迁移到其他处理器。linux内核进程调度器具有软CPU亲和性,不会再处理器之间频繁迁移,产生的负载小
  • 硬亲和性:利用linux内核提供给用户的API,强行将进程绑定到指定的CPU运行

相关functions

作者:jsdchenye
来源: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)(将某个cpu加进cpu集里)
  • void CPU_CLR(int cpu,cpu_set_t *set)(将某个cpu清除出cpu集里)
  • void CPU_ISSET(int cpu,const cpu_set_t *set)(判断某个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);
}

两个栗子
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);
    }   

    /* 设置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");
    }   

    /* 查看当前线程所运行的所有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个线程

pragma omp parallel for

告诉compiler将for loop并行

Getting faster using OpenMP

//他爸爸的太难了, 看不下去

相关文章

网友评论

      本文标题:Thread

      本文链接:https://www.haomeiwen.com/subject/pudqzftx.html