ホームページ  >  記事  >  バックエンド開発  >  [基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょう

[基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょう

Go语言进阶学习
Go语言进阶学习転載
2023-07-20 16:35:32808ブラウズ
みなさんこんにちは。Python が生産性の高い言語であることは誰もが知っています。私も Python がとても好きです。作業を最高の効率で完了するために Python をよく使用します。しかし、Python のパフォーマンス、特に大きな GIL ロックは私たちが批判してきた問題であり、それについて考えるとハエを食べているような気分になることがあります。

もちろん、現在私たちのプログラムのほとんどは (IO) ネットワーク集約型プログラムであり、それには Python で十分ですが、既存のプロジェクトがある場合や、開発するプロジェクトには、計算量を多く必要とするプログラミング シナリオがあります。どうすればよいですか?

友人の中には、Python C\C について聞いたことがあるかもしれません。C\C を使用して、Python の計算負荷の高い部分を書き換えてパフォーマンスを向上させています。

もちろん、これは良い解決策ですが、C\C には学習コストがかかることはわかっています。これより良い解決策はありますか?



/2 Python で Golang コードを呼び出してみる/

その後、幸運にも Golang に出会うことができ、しばらく使ってみた後、編集者は、Python で Go コードを呼び出せたら素晴らしいのに、と考えました。 C\C を学びたくありません。結局のところ、C\C ポインタや自分でメモリを解放するにはまだいくつかの障壁がありますが、Go は非常に便利です。自動ガベージ コレクションがあり、メモリ リークを節約し、本質的に高い利点があります。同時並行性。

常に情報を調べ、いくつかの落とし穴を踏んだ結果、苦労が報われ、ついに適切な方法を見つけたので、それを皆さんと共有したいと思います。

現在最も広く使用されている Python インタープリタは CPython です。Python には C\C コードを呼び出すことができるモジュールがあるだけです。Go は、いくつかの方法で Python と同様の呼び出し可能なコードにコンパイルすることもできます。メソッド。C\C ファイル。


/3 テスト環境/

システムwindows

Python インタプリタ

Python 3.7.6(64 ビット)

Go コンパイラ

:Go 1.14(64 ビット)


/4 パフォーマンス比較/

より良く反映するために最適化後、計算負荷の高い状況で 2 つの言語の違いを大まかに比較できます。

テスト: 1 億 (100000000) の累積を計算して、多数の計算をシミュレートします。

#1) Python コード

import time

def run(n):
    sum = 0
    for i in range(n):
        sum += i
    print(sum)


if __name__ == '__main__':
    startTime = time.time()
    run(100000000)
    endTime = time.time()
    print("耗时:", endTime - startTime)


が表示されます。所要時間:下図に示すように約 10 秒。

[基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょう


2) コードに進みます

package main

import (
  "fmt"
  "time"
)

func run(n int) {
  sum := 0
  for i := 0; i < n; i++ {
    sum += i
  }
  fmt.Println(sum)
}
func main() {
  var startTime = time.Now()
  run(100000000)
  fmt.Println("耗时:", time.Since(startTime))
}


次の図に示すように、約 200 ミリ秒かかることがわかります。

[基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょう


#

3)测试结论

    我们可以看到,在计算方面,Python和Go是有很大的差距的,如果计算这一块能放在Go上就好了。

    别着急,马上开始。


/5 Go代码编译为Python可调用的.so文件/

1)Go代码

功能:接收传入的值进行累加,并且返回最终的累加值。

package main

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

//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
}

func main() {
  //main函数中什么都不要写,和包名main要对应
}


2)编译为.so文件供Python调用。

命令如下:

go build -buildmode=c-shared -o 输出的.so文件 go源文件

例如:

go build -buildmode=c-shared -o s1.so s1.go


会生成.h文件和.so文件,.so文件供Python调用,如下图所示:

[基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょう


3)Ptyhon调用so文件

将上述生成的.so文件复制到Python项目的同一级目录。

[基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょう


4)Python代码

依然是计算一个亿,关键部分由Go生成的.so执行。

from ctypes import *
import time


if __name__ == &#39;__main__&#39;:
    startTime = time.time()

    s = CDLL("s1.so")  # 加载s1.so文件
    result = s.run(100000000)  # 调用Go生成的.so文件里面的run函数
    print("result:", result)

    endTime = time.time()
    print("耗时:", endTime - startTime)


可以看到耗时:0.11s左右,如下图所示。

[基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょう


5)为什么计算的耗时时间不一致,难道是计算错了???

    我们可以看到,虽然速度很快,但是Python在调用Go生成的.so文件之后,拿到的返回值竟然是错的,但是在Go中打印的确实对的,这是为什么呢???

    不要慌,问题不大!我们来计算一次稍微小一点的,上个100w的。


[基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょう


额,怎么还是错误。


6)我们再来计算更小一些的数,以10023为例,一个不零不整的数值。

[基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょう

今回は、結果が正しいことがわかります。しかし、なぜ 100 万という結果が間違っているのでしょうか? ? ?

上記のことから、.so ファイルの計算結果は正しいことがわかります。python がそれを受け取ったときに変換が間違っていた可能性もありますが、心配しないでください。この章には少し時間がかかりました。この落とし穴は次の章で必ず解決されますので、お楽しみに~

/6 概要/


おそらく Python Go は、Python C/C に比べて主要なパフォーマンスの改善において最適ではありませんが、この方法が最も心配が少ないと思います。すべて、C\C のしきい値は比較的高いです。
しかしそうは言っても、現状のパフォーマンスで十分かもしれませんし、結局のところ、Python Go は Python C\C よりも数倍効率的である可能性があります。

以上が[基礎] Python+Go - コンピューティングのパフォーマンスを向上させる別の方法を見つけてみましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はGo语言进阶学习で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。