4

私が取り組んでいるプロジェクトでは、Go から一連の C 関数を使用する必要があります。現在の実装では cgo を使用してそれを実現していますが、これを行うとパフォーマンスに大きな影響が生じるため、これを取り除こうとしています。

  • cgo はすべての C コードを syscall としてマークし、必要に応じてスケジューラに新しいスレッドを割り当てさせます。プロジェクトの CPU 時間の約 80% が重い C 作業に費やされているため、すぐに多くのスレッド ( GOMAXPROCS(= 8) ではなく 500 以上) を持つことになり、Linux カーネルはこれをあまり好みません。
  • 通常の「リミッター」アプローチ (バッファリングされたチャネルに cgo 呼び出しをロックさせる) を行うと、多数のミューテックスが発生し、プログラムの速度が低下します。

Go は並行性を管理する優れた方法であるため、このプロジェクトでは引き続き Go を使用したいと考えています。

私が試したこと:

  • のようなものをコメントアウトします (あまり役に立たないようentersyscall()src/runtime/cgocall.go、Go コードの変更は避けたいと思います)。
  • 私のコードを .c ファイルに入れて、.c なしで Go から呼び出しますimport "C"。ここで運が悪い-関数を呼び出すことができず、関数名を書いたときにpackage·function、コンパイラがファイル内の無効な文字について不平を言った。
  • .s ファイルを使用し、それをアセンブリとして記述します。私のasmはそれほど素晴らしいものではなく、理解できませんでした。

だから、私の質問は: cgo のオーバーヘッドを回避しながら、Go から C 関数をどのように使用するのですか?

補足: cgo がすべての呼び出しを syscall としてマークする理由はわかっていますが、この特定のケースでは、呼び出す関数はロックまたは IO でブロックされません。

4

1 に答える 1

0

あなたがしたいことは不可能です。C コードのオーバーヘッドが高いのには理由があります。これは、C コードが、Go が使用する短いスタックをサポートしない別の ABI (プラットフォームのネイティブ ABI) を使用するためです。したがって、Go コードが C コードを呼び出すたびに、スレッドのネイティブ スタックで実行を継続する必要があります。これにより、オーバーヘッドが発生します。このオーバーヘッドを取り除く方法はありません。考えてみてください。オーバーヘッドが必要ない場合、オーバーヘッドは存在しません。

プログラムがどのように見えるかを知らずに、代わりに何をすべきかを言うのは困難です。

于 2015-01-24T17:13:36.397 に答える