在Go应用程序中使用C(++)以获得性能 [英] Using C(++) in a Go application for performance

查看:62
本文介绍了在Go应用程序中使用C(++)以获得性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几天前,我开始研究Go,并从中了解了CGO和gccgo编译器.据我了解,这允许Go程序使用Go编译器进行编译,并使用C编译器编译C库,并从Go程序内部引用这些库.这对我来说真的很有趣,因为这使我们能够以很少的开销利用主程序中C的性能(如果需要).

但是我不确定那是多少,所以我在这里问:

在某些情况下,您会创建一个C库只是为了从Go应用程序内部使用它吗?还是此功能只是为了促进现有C代码的可重用性?

P.S:我想目前CGO不支持C ++,但是这里有人发表了一篇文章,说有人能够使用C函数包装C ++代码并成功调用它们.

解决方案

Cgo相当慢,因为Go必须这笔费用的情况.它与并行,分布式,GPU等编程类似,尽管启动成本略低.

汇编程序要好得多,因为您可以编写使用Go的调用约定的汇编程序,否则可以像本机Go代码一样对待汇编程序,但是汇编程序的可移植性差得多,难以阅读,并且维护繁重.实际上,Go标准库以Plan 9样式的程序集编写了一些 math big 程序包.

Gonum 是这两个示例.它对某些功能使用通用的汇编功能,这些功能可以通过这种方式更快地完成,但同时也利用了blas和lapack引擎.它确实提供了 Go-blas 的实现,但是C-blas(通常最终称为Fortran-blas)速度更快,并且对于大型矩阵计算而言,几乎总是比离开Go的成本小.

通常,您希望在可能的情况下避免使用cgo.仅在需要大量计算时间的情况下使用它,您需要与纯Go交互的非平凡事物进行交互,例如图形或音频驱动程序,或访问OpenCV之类的通用库.即使这样,如果您真的很在意性能,那么可能有必要实现某种调用池",在这种情况下,您可以从Go端安排多个调用,并通过一次将上下文切换到C一次执行所有调用.

对于C ++,存在一些重大问题.如果没有多层抽象,可能很难包装某些库(因为cgo无法正确处理包含的C ++头文件).另外,带有析构函数的C ++类实际上不能按值返回,而必须在堆上分配.由于Go不允许确定性地确定资源,因此您必须提供显式释放内存的功能,并且Go用户必须记住释放资源.(您可以在文档中找到一个名为 runtime.SetFinalizer 的功能,但我不能说我见过有人使用过该功能,文档本身附带了许多警告)/p>

诸如 defer 之类的功能使此操作更易于管理,但它破坏了RAII之类的东西,这些东西使现代C ++实践更安全.

I've started studying Go a couple of days ago and came by its CGO thing and the gccgo compiler. From my understanding this allows a Go program to compile using the Go compiler and compile C libraries using a C compiler and reference those libraries from inside a Go program. This is really interesting to me because this allows us to leverage C's performance (if needed) from our main program with little overhead.

However I'm not sure how little that is, so I'm asking here:

Are there cases where you would create a C library just to use it from inside your Go application? Or is this feature only to facilitate re-usability of existing C code?

P.S: I think at the moment CGO doesn't support C++ but there was a post here of someone that was able to wrap C++ code using C functions and call them successfully.

解决方案

Cgo is fairly slow, because Go has to mess with its runtime and calling conventions in certain ways to call C functions. The only place it's really worth it is cases where the compute time significantly dwarfs this cost. It's similar to parallel, distributed, GPU and so on programming, albeit with slightly lower startup costs.

Assembly is much better, because you can write assembly that uses Go's calling convention, and is otherwise treated like native Go code, but assembly is far less portable, harder to read, and more maintenance heavy. In fact, the Go standard library writes some of the math and big packages in Plan 9-style assembly.

Gonum is an example of both of these. It uses common assembly for some functions that can be done more quickly that way, but it also leverages blas and lapack engines. It does provide a Go-blas implementation, but C-blas (which is usually ultimately Fortran-blas) is faster, and for large matrix computations almost always dwarfs the cost of leaving Go.

Generally, you want to avoid cgo when possible. Only use it when significant computation time is needed, or you need to interact with things that would be non-trivial to interact with in pure Go, such as graphics or audio drivers, or accessing common libraries like OpenCV. Even then, if you really care about performance, where possible it may be worth it to implement some sort of "call pooling" where you can schedule multiple calls from the Go side and execute them all at once with a single context switch to C.

Edit: As for C++, there are some significant issues. It can be difficult to wrap certain libraries without several layers of abstraction (since cgo cannot handle included C++ headers properly). In addition, C++ classes with destructors can't really be returned by value and have to be allocated on the heap. Since Go doesn't allow for deterministic finalization of resources, you must provide a function to explicitly free memory, and the Go user must remember to free the resource. (There is a function you may read about in the documentation called runtime.SetFinalizer but I can't say I've ever seen anyone use it, and the documentation itself comes with a bunch of caveats)

Functionality such as defer makes this more manageable, but it ruins a lot of things like RAII which make modern C++ practices safer.

这篇关于在Go应用程序中使用C(++)以获得性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆