[問題] 用pthread_cond_wait來切換thread
開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
Linux + Raspberry Pi 1 + gcc 4.8
額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
pthread, sys/mman
問題(Question):
我希望用有效的thread管理來避免不必要的context switch
int main()裏面有個loop是每loop一次 sleep 5ms
在這5ms裏面可以用來處理被喚醒的thread: pid_1~4
程式最後會顯示每個loop耗費的時間 (完美結果會是5000,單位us)
(為了把scheduling的影響減到最小,已經把priority設到最高,也做了mlockall)
餵入的資料(Input):
預期的正確結果(Expected Output):
我輸出的結果每個loop時間為5200-5700us不等
請問還有無再優化的可能?
程式碼(Code):(請善用置底文網頁, 記得排版)
好讀程式碼:
https://gist.github.com/gnitnaw/6129098182bfd1f7c607
或以下:
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <sys/mman.h>
#define NLOOP 30
int global_thread = 0;
pthread_mutex_t mutex;
pthread_cond_t cond[5];
void _usleep(int micro)
{
struct timespec req = {0};
req.tv_sec = 0;
req.tv_nsec = micro * 1000L;
nanosleep(&req, (struct timespec *)NULL);
}
void* Thread(void* x) {
int i;
int *X = (int*) x;
for (i=0; i<5; ++i) {
pthread_mutex_lock(&mutex);
printf("This thread should sleep %d000 microsecond\n", *X);
while (global_thread != *X) {
printf("Thread %d wait\n", *X);
pthread_cond_wait(&cond[*X], &mutex);
}
printf("Thread %d Enter!\n", *X);
global_thread = 0;
pthread_mutex_unlock(&mutex);
_usleep(*X * 1000);
}
printf("Thread %d Exit! \n", *X);
pthread_exit(NULL);
}
int main(void) {
struct sched_param sp;
memset(&sp, 0, sizeof(sp));
sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
//sp.sched_priority = 49;
sched_setscheduler(0, SCHED_FIFO, &sp);
mlockall(MCL_CURRENT | MCL_FUTURE);
int i;
int a=1, b=2, c=3, d=4;
float dt[NLOOP];
struct timespec tp1, tp2;
unsigned long startTime, procesTime;
pthread_t pid_1, pid_2, pid_3, pid_4;
for (i=0; i<5; ++i) {
pthread_cond_init(&cond[i],NULL);
}
pthread_mutex_init(&mutex,NULL);
pthread_create(&pid_1,NULL,Thread, (void*)&a);
pthread_create(&pid_2,NULL,Thread, (void*)&b);
pthread_create(&pid_3,NULL,Thread, (void*)&c);
pthread_create(&pid_4,NULL,Thread, (void*)&d);
sleep(5);
puts("============================================");
clock_gettime(CLOCK_REALTIME, &tp1);
startTime = tp1.tv_sec*1000000000 + tp1.tv_nsec;
for (i=0; i<NLOOP; ++i) {
puts("");
printf("LOOP %d\n", i);
global_thread = i%5;
if (global_thread <5) pthread_cond_signal(&cond[global_thread]);
_usleep(5000);
clock_gettime(CLOCK_REALTIME, &tp2);
startTime = tp1.tv_sec*1000000000 + tp1.tv_nsec;
procesTime = tp2.tv_sec*1000000000 + tp2.tv_nsec - startTime;
dt[i] = (float)procesTime /1000.0;
tp1 = tp2;
}
pthread_join(pid_1, NULL);
pthread_join(pid_2, NULL);
pthread_join(pid_3, NULL);
pthread_join(pid_4, NULL);
for (i=0; i<NLOOP; ++i) {
printf("%d, %f\n", i, dt[i]);
}
return 0;
}
補充說明(Supplement):
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 86.200.210.189
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1446561206.A.F56.html
推
11/03 22:59, , 1F
11/03 22:59, 1F
→
11/03 23:00, , 2F
11/03 23:00, 2F
→
11/03 23:01, , 3F
11/03 23:01, 3F
→
11/03 23:01, , 4F
11/03 23:01, 4F
→
11/03 23:01, , 5F
11/03 23:01, 5F
→
11/03 23:06, , 6F
11/03 23:06, 6F
推
11/03 23:14, , 7F
11/03 23:14, 7F
→
11/03 23:15, , 8F
11/03 23:15, 8F
→
11/03 23:24, , 9F
11/03 23:24, 9F
我要的效果就是這樣:(以下為部份執行結果)
LOOP 0 // 不管其他thread
LOOP 1
Thread 1 Enter! // pid_1醒來
This thread should sleep 1000 microsecond
Thread 1 wait // pid_1睡
LOOP 2
Thread 2 Enter! // pid_2醒
This thread should sleep 2000 microsecond
Thread 2 wait // pid_2睡
LOOP 3
Thread 3 Enter! // pid_3醒
This thread should sleep 3000 microsecond
Thread 3 wait // pid_3睡
LOOP 4
Thread 4 Enter! // pid_4醒
This thread should sleep 4000 microsecond
Thread 4 wait // pid_4睡
最後顯示每個loop用掉的時間:
0, 5137.000000
1, 5192.000000
2, 5180.000000
3, 5200.000000
4, 5366.000000
5, 5173.000000
6, 5462.000000
7, 5198.000000
8, 5193.000000
9, 5198.000000
10, 5170.000000
11, 5240.000000
12, 5203.000000
13, 5199.000000
14, 5285.000000
15, 5174.000000
16, 5200.000000
17, 5429.000000
18, 5201.000000
19, 5339.000000
20, 5243.000000
21, 5203.000000
22, 5403.000000
23, 5638.000000
24, 5225.000000
25, 5184.000000 // 所有的thread已經結束,不需要再context switch
26, 5183.000000
27, 5171.000000
28, 5181.000000
29, 5173.000000
如果每個loop用掉5.2ms我可以接受(nanosleep看起來準度就是這樣)
可是差到5.6ms就....
剛剛試過用select好像更糟
※ 編輯: wtchen (86.200.210.189), 11/03/2015 23:31:04
推
11/04 00:44, , 10F
11/04 00:44, 10F
→
11/04 00:45, , 11F
11/04 00:45, 11F
→
11/04 00:45, , 12F
11/04 00:45, 12F
→
11/04 00:47, , 13F
11/04 00:47, 13F
→
11/04 00:47, , 14F
11/04 00:47, 14F
→
11/04 00:57, , 15F
11/04 00:57, 15F
→
11/04 01:00, , 16F
11/04 01:00, 16F
推
11/07 05:08, , 17F
11/07 05:08, 17F
→
11/07 05:29, , 18F
11/07 05:29, 18F
→
11/10 20:13, , 19F
11/10 20:13, 19F
→
11/10 20:13, , 20F
11/10 20:13, 20F
推
11/11 16:21, , 21F
11/11 16:21, 21F
→
11/11 21:42, , 22F
11/11 21:42, 22F
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章