2016-06-22 23 views
6

私は数日前にGoを学習し始め、CGOとgccgoコンパイラから来ました。私の理解から、これは、GoプログラムがGoコンパイラを使用してコンパイルし、Cコンパイラを使用してCライブラリをコンパイルし、それらのライブラリをGoプログラム内から参照できるようにします。これは、私たちがメインプログラムのCのパフォーマンス(必要に応じて)をほとんどオーバーヘッドで活用できるようにするため、私にとって本当に面白いです。GoLangアプリケーションでC(++)を使用してパフォーマンスを向上させる

私はそれがどのように少しわからないので、私はここで聞いてるのよしかし:

は、あなたは自分のGoアプリケーション内からそれを使用するCライブラリを作成します例はありますか?あるいは、この機能は、既存のCコードの再利用性を促進するためのものですか?

P.S:CGOはC++をサポートしていないと思いますが、Cの関数を使ってC++コードをラップして正常に呼び出せる人がいました。

+1

ほとんどの場合、再利用の可能性が高いです。ほとんどすべての主要ライブラリ(OSはもちろん)にはCバインディングがあります。したがって、あなたの言語からCを呼び出す能力を持つことは、その言語の採用にとって大きな勝利です。 – Dan

答えて

7

Cgoは、C関数を呼び出す特定の方法でmess with its runtime and calling conventionsになっているので、Cgoはかなり遅いです。それが本当に価値のある唯一の場所は、計算時間が大幅に短縮されたケースです(this cost)。わずかな起動コストでも、並列、分散、GPUなどのプログラミングと似ています。あなたが行くの呼び出し規約を使用し、それ以外の場合はネイティブゴーコードのように扱われているアセンブリを書くことができますので、

総会は、はるかに良いですが、アセンブリは、はるかに読みにくく、ポータブル、およびより多くのメンテナンス重いです。実際、Go標準ライブラリは、mathbigパッケージのいくつかをPlan 9スタイルのアセンブリに書き込みます。

Gonumは、この両方の例です。この方法では、より迅速に行うことができる機能のために共通のアセンブリを使用しますが、blasエンジンとlapackエンジンも活用します。 Go-blasの実装を提供しますが、C-blas(通常は最終的にはFortran-blas)は高速で、大規模な行列計算ではほとんどの場合、Goを離れるコストが大きくなりません。

一般的に、可能な場合はcgoを避けたいと考えています。大幅な計算時間が、あなたは、このようなグラフィックやオーディオドライバ、またはOpenCVのような共通のライブラリにアクセスすると、純粋な移動にと相互作用する非自明だろう物事と対話する必要が、を必要に応じて、またはされた場合にのみ、それを使用しています。それでも、実際にパフォーマンスを気にしているなら、Go側からの複数のコールをスケジュールして、Cへの1回のコンテキスト切り替えですべてを一度に実行できる「コールプーリング」を実装する価値があります。

編集:C++については、いくつかの重大な問題があります。いくつかの抽象レイヤーなしで(cgoはインクルードされたC++ヘッダーを適切に処理できないため)特定のライブラリをラップするのは難しいでしょう。さらに、デストラクタを持つC++クラスは実際には値で返すことができず、ヒープ上に確保する必要があります。 Goは、リソースの決定論的ファイナライズはできませんので、あなた明示的に空きメモリ、およびゴーユーザーがリソースを解放するために覚えておく必要がありますする機能を提供しなければなりません。(そこがruntime.SetFinalizerと呼ばれるドキュメント内で約読むことができる機能ですが、私は私が今まで誰もがそれを使用して見てきたと言うことはできません、およびドキュメント自体は、警告の束が付属しています)deferがこれを作るなど

機能現代的なC++のプラクティスをより安全にするRAIIのようなものがたくさんあります。

+0

"Goは、C関数を呼び出すためにランタイムを一定の方法で中断しなければなりません" - それはどこかで文書化され/議論されていますか? [my answer](http://stackoverflow.com/a/37962500/3169754)と[this thread](https://groups.google.com/forum/#!topic/golang-nuts/RTtMsgZi88Q)も参照してください。 – gavv

+0

ランタイムが中断されているというエビデンスは見つかりません。私はおそらく何かが欠けているでしょう。 – gavv

+1

@ g-vこれは、常に新しいGoバージョンで流行しているものの1つです。私は、ゴーはガベージコレクターなどを完全に休止しなければならないと思った。今日では、さまざまな呼び出し規約に対応するために大部分のメタデータを記録する必要があるようです: http://dave.cheney.net/2016/01/18/cgo-is-not-go また、他のスレッドでgoroutineを中断して再スケジュールすることはできません。これはCコード内にありますが、パフォーマンス上の理由から、GOコードでは絶対にできます。 – LinearZoetrope

1

1回の呼び出しでCライブラリが多くの作業をしない限り、パフォーマンスのためだけにCコードを記述しません。私はcgoが古いコードとのインタフェースのためだけであると考えます。

理由はcgoオーバーヘッドです。現在、cgo関数への関数呼び出しはbetween 50 and 100 times slower than function calls to Go codeです。 cgo関数呼び出しのオーバーヘッドは衝撃的です。

関連する問題