2016-06-22 5 views
6

Я начал изучать Go пару дней назад и пришел к его CGO и компилятору gccgo. По моему мнению, это позволяет программе Go компилировать с использованием компилятора Go и компилировать библиотеки C с использованием компилятора C и ссылаться на эти библиотеки из программы Go. Это действительно интересно для меня, потому что это позволяет нам использовать производительность C (если необходимо) из нашей основной программы с небольшими накладными расходами.Использование C (++) в приложении GoLang для производительности

Однако я не уверен, как мало что есть, поэтому я спрашиваю здесь:

Есть ли случаи, когда вы бы создать библиотеку C просто использовать его внутри вашего приложения Go? Или эта функция предназначена только для облегчения повторного использования существующего кода C?

P.S: Я думаю, что на данный момент CGO не поддерживает C++, но здесь был кто-то, кто смог обернуть C++-код с помощью функций C и назвать их успешно.

+1

Скорее всего, только для повторного использования. Почти каждая основная библиотека (не говоря уже о ОС) имеет привязку C, поэтому возможность вызова C с вашего языка является большой победой для принятия языка. – Dan

ответ

7

Cgo довольно медленный, потому что Go имеет mess with its runtime and calling conventions определенным образом для вызова функций C. Единственное место, в котором это действительно стоит, - это случаи, когда время вычисления значительно затмевает this cost. Он похож на параллельный, распределенный, графический процессор и т. Д. Программирование, хотя и с несколько меньшими затратами на запуск.

Сборка намного лучше, потому что вы можете написать сборку, которая использует соглашение о вызове Go, и в противном случае рассматривается как собственный код Go, но сборка гораздо менее переносима, сложнее для чтения и больше обслуживания. Фактически, стандартная библиотека Go записывает некоторые из пакетов math и big в сборке Plan 9.

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++ более безопасными.

+0

«Go должен приостанавливать свое время выполнения определенным образом для вызова функций C» - он где-то документирован/обсужден? См. Также [мой ответ] (http://stackoverflow.com/a/37962500/3169754) и [этот поток] (https://groups.google.com/forum/#!topic/golang-nuts/RTtMsgZi88Q). – gavv

+0

Я не могу найти никаких доказательств того, что время исполнения приостановлено. Вероятно, я что-то пропустил. – gavv

+1

@ g-v Это одна из тех вещей, которая постоянно меняется с новыми версиями Go. Я думаю, что Go привык к тому, чтобы просто приостановить сборщик мусора и другие вещи. Похоже, что в настоящее время в основном приходится записывать тонну метаданных для размещения различных соглашений о вызовах: http://dave.cheney.net/2016/01/18/cgo-is-not-go Кроме того, это не может прерывать и перенести goroutine на другой поток, пока он находится в коде C, который является абсолютным и может делать, часто по соображениям производительности, код GO. – LinearZoetrope

1

Если библиотека C не выполняет много работы за один вызов, я бы не написал код C только для производительности. Я считаю, что cgo только для взаимодействия со старым кодом.

Причина - накладные расходы cgo. В настоящее время вызовы функций в функции cgo: between 50 and 100 times slower than function calls to Go code. Накладные расходы на вызовы функций cgo шокируют.

Смежные вопросы