先给结论:网络瓶颈用线程,cpu瓶颈用进程

运行条件

16核 ubuntu python3+

闲置情况

top-1命令,可以看到16核基本上没负载(us值)

Python单核跑满cpu

1
2
3
4
5
6
def lp(): 
while 1:
a = 1
b = 2
c = b + a
lp()
单核代码,占满了cpu5

三线程Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

import time

def add_num():
while 1:
a = 1
b = 2
c = b + a

if __name__ == '__main__':
t1 = Thread(target=add_num)
t2 = Thread(target=add_num)
t3 = Thread(target=add_num)
t3.start()
t1.start()
t2.start()
time.sleep(100)
可以看到是0 4 7三个核在负载,而且无法跑满,连50%都跑不到,但是34+37+40 = 111 这时就有个猜想,是否线程本质只占一个cpu

试试开一个线程,是可以跑满100的

两线程

相加为100%

三进程

可以看到是07 11 13三个核在负载,全部跑满100%

两线程C代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void print_message_function (void *ptr);

int main()
{
int tmp1, tmp2;
void *retval;
pthread_t thread1, thread2;
char *message1 = "thread1";
char *message2 = "thread2";

int ret_thrd1, ret_thrd2;

ret_thrd1 = pthread_create(&thread1, NULL, (void *)&print_message_function, (void *) message1);
ret_thrd2 = pthread_create(&thread2, NULL, (void *)&print_message_function, (void *) message2);

// 线程创建成功,返回0,失败返回失败号
if (ret_thrd1 != 0) {
printf("线程1创建失败\n");
} else {
printf("线程1创建成功\n");
}

if (ret_thrd2 != 0) {
printf("线程2创建失败\n");
} else {
printf("线程2创建成功\n");
}

//同样,pthread_join的返回值成功为0
tmp1 = pthread_join(thread1, &retval);
printf("thread1 return value(retval) is %d\n", (int)retval);
printf("thread1 return value(tmp) is %d\n", tmp1);
if (tmp1 != 0) {
printf("cannot join with thread1\n");
}
printf("thread1 end\n");

tmp2 = pthread_join(thread1, &retval);
printf("thread2 return value(retval) is %d\n", (int)retval);
printf("thread2 return value(tmp) is %d\n", tmp1);
if (tmp2 != 0) {
printf("cannot join with thread2\n");
}
printf("thread2 end\n");

}

void print_message_function( void *ptr ) {
int i = 0;
while(1)
{
i++;
}
}

C的多线程没有这个问题

现象:

python的线程只能用到一个核。

结论

个人查资料后的判断结论是:python用到了GIL锁导致python线程只能用到一个核
Reference :
https://timber.io/blog/multiprocessing-vs-multithreading-in-python-what-you-need-to-know/