【python】ctypes向c函数传入二维数组、利用c链接库提升python速度

9 篇文章 0 订阅


前言

既然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文档


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值