前言
既然Cpython的多线程不堪重用,多进程又有诸多限制,那么对于计算密集型任务我们可以用
c语言链接库的方式,将计算任务交给c语言完成,python作为胶水语言。
还是以冒泡排序作为实验对象。
步骤
编写c语言函数
#include "stdio.h"
#include "pthread.h"
#include "stdlib.h"
#include "sys/time.h"
typedef struct {
int* arr;
int size;
} num_array;
// 进行排序的函数
void *BubbleSort(void *data)
{
num_array *p = (num_array *)data;
int *arr = p->arr;
int size = p->size;
int i, j, tmp;
for (i = 0; i < size - 1; i++) {
for (j = 0; j < size - i - 1; j++) {
if (arr[j] > arr[j+1]) {
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
return NULL;
}
// 暴露给python的函数,此函数使用多线程+
int ** doit(int **arr,int arr_num, int arr_size){
pthread_t ths[arr_num]; // 创建线程id数组
num_array *a_s[arr_num]; // 创建传入排序函数的结构体数组
for (int j=0;j<arr_num;j++){ // 遍历外层数组
a_s[j] = malloc(sizeof(num_array)) ;
a_s[j]->size = arr_size;
a_s[j]->arr = arr[j];
}
for(int i=0;i<arr_num;i++){
pthread_create(&(ths[i]), NULL, BubbleSort, (void *)a_s[i]); // 创建线程
}
for(int i=0;i<arr_num;i++){
pthread_join(ths[i], NULL); // 等待
}
return arr;
}
编译c代码为so文件
我的c代码文件为bub.c
命令:
gcc -fpic -shared -o bub.so bub.c -lpthread
编写python代码
参考链接:ctypes文档
import time
from ctypes import *
ARRAY_NUM = 5
ARRAY_SIZE = 50000
if __name__ == '__main__':
"""
最终传入c函数的是类似
[
[5,4,3,2,1],
[5,4,3,2,1]
]的二维数组,在c函数形参中表现为int **
"""
c_int_array = (POINTER(c_int) * ARRAY_NUM)() # ctypes的外层数组
for c in range(ARRAY_NUM): # 向外层数组放入添加好内容的内层数组
tmp = []
for d in range(ARRAY_SIZE): # 添加内层数组内容
tmp.append(ARRAY_SIZE - d)
c_int_array[c] = (c_int * ARRAY_SIZE)(*tmp)
dll = cdll.LoadLibrary("./bub.so") # 加载自己的so文件
time_start = time.time()
res = dll.doit(c_int_array, ARRAY_NUM, ARRAY_SIZE) # 执行c函数
time_mid = time.time() # 打印下执行函数的时间
print("do main work time used :", time_mid - time_start) # do main work time used : 4.026979684829712
# 将ctypes的 int** 重新转换为数组
# 由于没有找到ctypes中自带的将ctypes类型转化为python内置类型的函数,所以我迭代了下
# 由于传入c函数的是指针,所以是直接在c_int_array上排序的
res_array = []
for i in range(ARRAY_NUM):
tmp = []
for j in range(ARRAY_SIZE):
tmp.append(c_int_array[i][j])
res_array.append(tmp)
# print(res_array) 打印发现确实已经排序完成
time_end = time.time()
print("cast ctypes to list time used :", time_end - time_mid) # cast ctypes to list time used : 0.039121150970458984
接下来直接执行python代码即可
关于
函数返回值接收的问题请查看ctypes文档