簡體   English   中英

在 Go 應用程序中使用 C(++) 來提高性能

[英]Using C(++) in a Go application for performance

幾天前我開始學習 Go 並學習了它的 CGO 和 gccgo 編譯器。 根據我的理解,這允許 Go 程序使用 Go 編譯器進行編譯,並使用 C 編譯器編譯 C 庫,並從 Go 程序內部引用這些庫。 這對我來說真的很有趣,因為這使我們能夠以很少的開銷從主程序中利用 C 的性能(如果需要)。

但是我不確定那有多少,所以我在這里問:

是否存在創建 C 庫只是為了在 Go 應用程序內部使用它的情況? 或者這個特性只是為了促進現有 C 代碼的可重用性?

PS:我認為目前 CGO 不支持 C++,但這里有一篇文章,有人能夠使用 C 函數包裝 C++ 代碼並成功調用它們。

Cgo 相當慢,因為 Go 必須弄亂它的運行時和以某些方式調用 C 函數的調用約定 唯一真正值得的地方是計算時間大大超過此成本的情況 它類似於並行、分布式、GPU 等編程,盡管啟動成本略低。

匯編要好得多,因為你可以編寫使用 Go 調用約定的匯編,否則會像本地 Go 代碼一樣對待,但匯編的可移植性要差得多,更難閱讀,而且維護起來也更繁重。 事實上,Go 標准庫在 Plan 9 風格的匯編中編寫了一些mathbig包。

Gonum是這兩者的一個例子。 它對一些可以通過這種方式更快完成的功能使用通用匯編,但它也利用了 blas 和 lapack 引擎。 它確實提供了Go-blas實現,但 C-blas(通常最終是 Fortran-blas)更快,並且對於大型矩陣計算,幾乎總是使離開 Go 的成本相形見絀。

通常,您希望盡可能避免使用 cgo。 僅當需要大量計算時間時才使用它,或者您需要與純 Go 中無法交互的事物進行交互,例如圖形或音頻驅動程序,或訪問 OpenCV 等公共庫。 即便如此,如果你真的關心性能,在可能的情況下實現某種“調用池”可能是值得的,你可以從 Go 端安排多個調用,並通過單個上下文切換到 C 來一次執行它們。

編輯:至於 C++,有一些重要的問題。 如果沒有幾個抽象層,就很難包裝某些庫(因為 cgo 無法正確處理包含的 C++ 頭文件)。 此外,帶有析構函數的 C++ 類不能真正按值返回,必須在堆上分配。 由於 Go 不允許資源的確定性終結,您必須提供一個函數來顯式釋放內存,並且 Go 用戶必須記住釋放資源。 (您可以在名為runtime.SetFinalizer的文檔中讀到一個函數,但我不能說我曾經見過任何人使用它,而且文檔本身帶有一堆警告)

諸如defer功能使這更易於管理,但它破壞了許多諸如 RAII 之類的東西,這些東西使現代 C++ 實踐更安全。

除非 C 庫在一次調用中完成大量工作,否則我不會僅僅為了性能而編寫 C 代碼。 我認為 cgo 僅用於與舊代碼交互。

原因是 cgo 開銷。 目前,對 cgo 函數的函數調用比對 Go 代碼的函數調用慢 50 到 100 倍 cgo 函數調用的開銷令人震驚。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM