我有一个多线程的C语言基准测试程序,可以描述如下:
Thread 1 Thread 2 Thread 3 Control thread
while(1) while(1) while(1) while(1)
| | |
| | | |
| | | every one second:
| | | wait for other threads to be blocked
| | | do something with S values
| | | |
| | | |
write S1 write S2 write S3 |
| | | |
| | | |
barrier barrier barrier barrier
我的问题涉及上图中的等待其他线程被阻塞
语句。目前,我想到了以下解决方案来实现它:
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <inttypes.h>
#define NB_THREADS 11
pthread_barrier_t b;
uint8_t blocked_flags[NB_THREADS] = {0};
pthread_mutex_t blocked_flags_mutexes[NB_THREADS];
uint64_t states[NB_THREADS] = {0};
uint64_t time_diff_get(struct timespec *start, struct timespec *end) {
uint64_t end_ns = end->tv_sec * 1E9 + end->tv_nsec;
uint64_t start_ns = start->tv_sec * 1E9 + start->tv_nsec;
uint64_t res = end_ns - start_ns;
return res;
}
static void *worker_thread(void *arg) {
uint8_t id = *((uint8_t *)arg);
int a = 0;
while(1) {
for (int i = 0; i < 1000; i++) {
a++;
}
states[id]++;
pthread_mutex_lock(&blocked_flags_mutexes[id]);
blocked_flags[id] = 1;
pthread_mutex_unlock(&blocked_flags_mutexes[id]);
pthread_barrier_wait(&b);
pthread_mutex_lock(&blocked_flags_mutexes[id]);
blocked_flags[id] = 0;
pthread_mutex_unlock(&blocked_flags_mutexes[id]);
}
printf ("a = %d\n", a);
return NULL;
}
static void *control_thread() {
struct timespec last_time;
clock_gettime(CLOCK_REALTIME, &last_time);
while(1) {
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
if (time_diff_get(&last_time, &time) >= 1E9) {
// Wait for all threads to be blocked
for (int i = 0; i < NB_THREADS; i++) {
while (1) {
pthread_mutex_lock(&blocked_flags_mutexes[i]);
if (blocked_flags[i] == 1) {
pthread_mutex_unlock(&blocked_flags_mutexes[i]);
break;
}
pthread_mutex_unlock(&blocked_flags_mutexes[i]);
}
}
for (int i = 0; i < NB_THREADS; i++) {
pthread_mutex_lock(&blocked_flags_mutexes[i]);
if (blocked_flags[i] == 0) {
printf("How could I avoid to be there ??\n");
exit(-1);
}
pthread_mutex_unlock(&blocked_flags_mutexes[i]);
}
// Do some intersting stuff here with states array
// .....
// .....
// Save last time
clock_gettime(CLOCK_REALTIME, &last_time);
}
pthread_barrier_wait(&b);
}
return NULL;
}
int main() {
// Init barrier
pthread_barrier_init(&b, NULL, NB_THREADS + 1);
// Create worker threads
pthread_t threads[NB_THREADS];
uint8_t ids[NB_THREADS];
for (int i = 0; i < NB_THREADS; i++) {
ids[i] = i;
pthread_mutex_init(&blocked_flags_mutexes[i], NULL);
}
for (int i = 0; i < NB_THREADS; i++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(i + 1, &cpu_set);
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpu_set);
pthread_create(&threads[i], &attr, worker_thread, &ids[i]);
}
// Create control thread
pthread_t ctrl_thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(0, &cpu_set);
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpu_set);
pthread_create(&ctrl_thread, &attr, control_thread, NULL);
// Join on worker threads
for (int i = 0; i < NB_THREADS; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
但是,使用gcc -O0
编译的此基准测试在12核Intel平台上运行时,明显显示出我有一个"竞争"问题,因为进程总是在几秒钟后退出并显示消息。我该如何解决?
注意:根据其他问题,我考虑使用自定义屏障,但我需要继续使用pthread_barrier而不是在mutex和cond变量之上重新实现的barrier。