[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran

Lepaskan: 2023-07-20 16:32:25
ke hadapan
702 orang telah melayarinya
Dalam artikel sebelum ini, kami berjaya memanggil kod Go melalui Python dan menyerahkan pengiraan intensif kepada Go Walaupun pengiraan sangat pantas, apabila mendapat nilai pulangan, nampaknya agak mengejutkan, tidak seperti yang kami bayangkan .

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran


/2 Apakah sebab ralat nilai pulangan? /

Dalam artikel lepas, kita semua seolah-olah terlupa sekeping gambar.

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran


Fail .go kepunyaan Go, .jadi fail yang Python panggil Go. ? ? Ia seolah-olah tidak mempunyai rasa kewujudan Masalah kami terletak pada fail .h ini ditukar kepada C ialah jenis GoInt Apakah maksud jenis ini secara khusus? ? ? Tengok lagi.

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran

Anda mungkin boleh mengetahui daripada perkara di atas bahawa GoInt sebenarnya GoInt64, dan jenis GoInt64 adalah jenis long long Adakah ini sesuatu? ? ?

Malah, apabila kita memanggil fail .so dalam Python, kita menggunakan modul<code style="font-family: var(--monospace);vertical-align: initial;border-width: 1px;border-style: solid;border-color: rgb(231, 234, 237);background-color: rgb(243, 244, 244);border-radius: 3px;padding-right: 2px;padding-left: 2px;font-size: 0.9em;"><span style="font-size: 18px;">ctypes</span>ctypes, ini mempunyai jadual yang sepadan.

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran


/3 Python, ctypes, jadual surat menyurat jenis c/

alamat laman web rasmi:


🎜🎜c_charc_wcharc_bytec_ubyteintintc_ulonglongc_size_t ize_t atau Py_ssize_tfloat . floatbait objek  atau Tiadac_void_p


    根据上述表格我们可以发现,在C中的long long类型对应的ctype类型是c_longlong。

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran


    所以我们需要在Python将.so中的返回值改一下,不能使用系统默认的了。代码如下:

from ctypes import *
import time

class StructPointer(Structure):
    # 根据查表,C中的long long,对应的ctypes 是 c_longlong
    # _fields_必须是[](列表)类型,里面写对应的类型,固定格式
    _fields_ = [("p", c_longlong,),]

if __name__ == &#39;__main__&#39;:
    beginTime = time.time()
    s = CDLL("s1.so")  # 加载s1.so文件
    s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式
    result = s.run(100000000)  # 调用Go生成的.so文件里面的run函数

    print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应
    endTime = time.time()
    print("耗时:", endTime - beginTime)
Salin selepas log masuk


再次执行:

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran

可以看到,这次Python执行的结果和Go执行结果就一个样了。继续,换个数字试试看。

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran

基本可以确定,这次是没问题了。


/4 如果返回的是字符串呢?/

Go代码

package main

import (
  "C" //C必须导入
  "fmt"
)

//export run
func run(n int) int{
  /*
    必须要export 函数名
    //是注释的意思,相当于Python中的 #
    我也是第一次见注释还有作用
  */
  sum := 0
  for i := 0; i < n; i++ {
    sum += i
  }
  fmt.Println("我是Go代码,我跑完了,我的结果是:",sum)
  return sum
}

//export speak
func speak(n int) string{

  return "OMG 996好累呀,难得休息一天,好好休息"
}
func main() {
  //main函数中什么都不要写,和包名main要对应
}
Salin selepas log masuk


下面一起来理解.h文件。编译之后打开.h文件如下图所示:

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran


可以看到,在extern的函数成了两个,但是他的返回值是GoString,继续找。

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran


可以发现,其实GoString就是_GoString_,继续找。

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran

这次是一个结构体,里面其实是两个值,不在是单独的long long了,那Python中的继承类也要改一下了。

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran


下面基本同上。

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran

完整代码如下:

from ctypes import *
import time

class StructPointer(Structure):
    # 根据查表,C中的long long,对应的ctypes 是 c_longlong
    # _fields_必须是[](列表)类型,里面写对应的类型,固定格式
    _fields_ = [("p", c_longlong,),]

class StrPointer(Structure):
    # typedef struct { const char *p; ptrdiff_t n; } _GoString_;
    # ptrdiff_t == long long
    _fields_ = [("p", c_char_p), ("n", c_longlong)]

if __name__ == &#39;__main__&#39;:
    beginTime = time.time()
    s = CDLL("s1.so")  # 加载s1.so文件

    s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式
    result = s.run(100000798)  # 调用Go生成的.so文件里面的run函数
    print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应

    s.speak.restype = StrPointer
    speakStr = s.speak()
    # 返回的是字节类型,需要转字符串,返回的内容在.p中,.n是切的长度,后面会跟一些介绍,不需要
    speakStr = str(speakStr.p[:speakStr.n], encoding="utf-8")
    print("speak:",speakStr)

    endTime = time.time()
    print("耗时:", endTime - beginTime)
Salin selepas log masuk


结果:

[Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran

    可以看到,调用Go代码成功的拿到了正确的字符串返回值,如果没有 .restype = StrPointer拿到的会是什么呢?拿到会和原来的一样,一堆数字,这里就不举栗子了。


/5 小结/

    至此,基本上在Python调用Go代码上的大坑都解决了,最复杂的是返回字符串类型,查了很多相关资料才解决。

    关于返回其他类型的Python的class怎么写,我相信已经难为不到你们了,最复杂的都解决了,最简单的还不会吗?(除字符串类型以外其他_fields_都是一个字段的)

    我相信各位小伙伴学习能力还是很强的,人生苦短,Python当歌,加油,奥利给!

ctypes type C type Python type
c_bool bool (1)
char 1 aksara  bait objek
wchar_t  1-rentetan  1-rentetan
char int
unsigned char int
c_short short int
pendek tidak bertanda int
c_int int int
c_uint unsigned int int
long
🎜🎜🎜c_ulong🎜 unsigned long int
c_longlong __int64 atau long long
unsigned  __int64 atau unsigned long long int
size_t int
int c_float
apung
c_char_p char * (NUL  ditamatkan )
c_wchar_p wchar_t * (NUL  ditamatkan)
void * int atau Tiada

Atas ialah kandungan terperinci [Lanjutan] Python+Go - Mari cari cara lain untuk meningkatkan prestasi pengkomputeran. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:Go语言进阶学习
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan