Is it better to call Julia from C++ or call C++ from Julia?

1,636 views
Skip to first unread message

K leo

unread,
Sep 2, 2016, 8:51:21 PM9/2/16
to julia...@googlegroups.com
While the majority of my analytics are in Julia, I will need to use an external event handling API which is implemented in C++.  It looks that I have two options: 1) write the main code in C++ with the API and call Julia function for analytics; 2) write the main code also in Julia that work seamlessly with my analytics and call the C++ API for events.

Which would be the better path in terms of ease of coding and performance?

K leo

unread,
Sep 2, 2016, 8:55:38 PM9/2/16
to julia-users
I need to add that the target OS is Ubuntu.

Steven G. Johnson

unread,
Sep 2, 2016, 9:17:38 PM9/2/16
to julia-users


On Friday, September 2, 2016 at 8:51:21 PM UTC-4, K leo wrote:
While the majority of my analytics are in Julia, I will need to use an external event handling API which is implemented in C++.  It looks that I have two options: 1) write the main code in C++ with the API and call Julia function for analytics; 2) write the main code also in Julia that work seamlessly with my analytics and call the C++ API for events.

Which would be the better path in terms of ease of coding and performance?

Much easier to call C++ from Julia, particularly with the Cxx.jl package.   Performance-wise, it shouldn't matter, but it is always easier to write glue code in a higher-level language than in a lower-level language. 

Bart Janssens

unread,
Sep 3, 2016, 6:56:26 AM9/3/16
to julia...@googlegroups.com
Hi,

I'd say the better option in terms of performance depends on which path allows you to limit the number of calls into the other language, since there will often be some overhead in calling Julia from C++ or vice versa, even if it's just because things are less transparent to the compiler.

When calling a Julia function from C++, I think you always need to box the arguments, which may be slower than calling C++ from Julia. Also remember to cache the pointer to the Julia function, to avoid the name lookup on every call.

To call C++ functions from Julia, you can also use my CxxWrap package, which allows you to write the Julia interface as a C++ library:
https://github.com/barche/CxxWrap.jl

Cheers,

Bart

Steven G. Johnson

unread,
Sep 3, 2016, 8:31:33 AM9/3/16
to julia-users


On Saturday, September 3, 2016 at 6:56:26 AM UTC-4, Bart Janssens wrote:
When calling a Julia function from C++, I think you always need to box the arguments

No, it is possible to avoid this, because you can get a raw C function pointer to a Julia function compiled for a particular argument signature.  This is what happens for callbacks, for example.

K leo

unread,
Sep 3, 2016, 6:41:28 PM9/3/16
to julia-users
Thanks very much for the advise.

One question is whether Cxx is mature enough to be usable at this stage.  I tried to add it with Julia 0.5 and got the following errors:

julia> Pkg.add("Cxx")
INFO: Installing Cxx v0.0.1
INFO: Building Cxx
writing path.jl file
Tuning for julia installation at: /home/xxx/Software/julia-e6f843b073/bin
 g++ -D_GLIBCXX_USE_CXX11_ABI=0 -fno-rtti -DLIBRARY_EXPORTS -fPIC -O0 -g -std=c++11   -I/home/xxx/Software/julia-e6f843b073/bin/../../src/support -I/home/xxx/Software/julia-e6f843b073/bin/../include -Isrc/clang-3.7.1/lib -Ibuild/clang-3.7.1/include -Isrc/clang-3.7.1/include -Isrc/llvm-3.7.1/include -Ibuild/llvm-3.7.1/include  -DLLVM_NDEBUG -c ../src/bootstrap.cpp -o build/bootstrap.o
../src/bootstrap.cpp:19:35: fatal error: llvm/ADT/DenseMapInfo.h: No such file or directory
compilation terminated.
BuildBootstrap.Makefile:131: recipe for target 'build/bootstrap.o' failed
make: *** [build/bootstrap.o] Error 1
=================================[ ERROR: Cxx ]=================================

LoadError: failed process: Process(`make -j2 -f BuildBootstrap.Makefile BASE_JULIA_HOME=/home/xxx/Software/julia-e6f843b073/bin`, ProcessExited(2)) [2]
while loading /home/xxx/.julia/v0.5/Cxx/deps/build.jl, in expression starting on line 31

================================================================================

================================[ BUILD ERRORS ]================================

WARNING: Cxx had build errors.

 - packages with build errors remain installed in /home/xxx/.julia/v0.5
 - build the package(s) and all dependencies with `Pkg.build("Cxx")`
 - build a single package by running its `deps/build.jl` script

================================================================================
INFO: Package database updated

K leo

unread,
Sep 4, 2016, 12:22:36 AM9/4/16
to julia-users
The error of adding Cxx was eliminated by changing small bits in the makefile.  It builds successfully.  I am so surprised to find that it is such a huge package with over 1GB in size.

Uwe Fechner

unread,
Sep 4, 2016, 9:37:45 AM9/4/16
to julia-users
Could you explain your fix? I have the same error.

Uwe

Steven G. Johnson

unread,
Sep 4, 2016, 2:44:13 PM9/4/16
to julia-users


On Sunday, September 4, 2016 at 12:22:36 AM UTC-4, K leo wrote:
The error of adding Cxx was eliminated by changing small bits in the makefile.  It builds successfully.  I am so surprised to find that it is such a huge package with over 1GB in size.

It has to compile the entire LLVM C++ front-end. 

K leo

unread,
Sep 6, 2016, 2:08:54 AM9/6/16
to julia-users
in deps/BuildBootstrap.Makefile, put '+' in the line so it becomes as follows:

+LIB_DEPENDENCY += $(LIBDIR)/lib$(LLVM_LIB_NAME).$(SHLIB_EXT)

Then Pkg.build("CXX")

K leo

unread,
Sep 6, 2016, 2:11:34 AM9/6/16
to julia-users
Sorry, only the '+' before '=', no '+' at the beginning.  Correct way:
LIB_DEPENDENCY += $(LIBDIR)/lib$(LLVM_LIB_NAME).$(SHLIB_EXT)

Steven G. Johnson

unread,
Sep 6, 2016, 9:59:30 AM9/6/16
to julia-users


On Tuesday, September 6, 2016 at 2:08:54 AM UTC-4, K leo wrote:
in deps/BuildBootstrap.Makefile, put '+' in the line so it becomes as follows:

+LIB_DEPENDENCY += $(LIBDIR)/lib$(LLVM_LIB_NAME).$(SHLIB_EXT)

Then Pkg.build("CXX")

Could you submit a pull request to Cxx.jl with the patch? 

Tim Besard

unread,
Sep 6, 2016, 10:19:38 AM9/6/16
to julia-users
I already fixed this a while back, but Cxx hasn't been tagged since.

Op dinsdag 6 september 2016 09:59:30 UTC-4 schreef Steven G. Johnson:

simon rss

unread,
Sep 6, 2016, 10:41:17 AM9/6/16
to julia-users
Hello,  Bart Janssens. I have a question.

If eventually all things compile down to machine code, why those callings will have overhead? Why can't the compiler glue C part and julia part seamlessly at machine code level?

Another thing I am not sure is that, when we embed code like "jl_eval_string" into C and compile it to a exe. When running this exe, will it call julia engine to evaluate it(this should have huge overhead) or will all be done directly at machine code level(no overhead)?

Sorry if my question is nonsense, I am from physics background, just curious about the internal and care much about performance.

Steven G. Johnson

unread,
Sep 6, 2016, 11:11:27 AM9/6/16
to julia-users


On Tuesday, September 6, 2016 at 10:41:17 AM UTC-4, simon rss wrote:
Hello,  Bart Janssens. I have a question.

If eventually all things compile down to machine code, why those callings will have overhead? Why can't the compiler glue C part and julia part seamlessly at machine code level?

Calling C or C++ from Julia can have little or no overhead, because Julia's compiler knows about C.    The reverse is not necessarily true, because the C compiler doesn't know about Julia.   (However, if you compile a static C-callable interface to a Julia function with cfunction, then there is no more overhead to call this from C than any other C function pointer.)

(Caveat: cross-language inlining is not generally possible, nor can functions called from shared libraries or function pointers be inlined, so if you have very small functions it is more efficient to call them as Julia code within Julia code because then they can be inlined.)

Páll Haraldsson

unread,
Sep 6, 2016, 11:24:54 AM9/6/16
to julia-users

On Saturday, September 3, 2016 at 1:17:38 AM UTC, Steven G. Johnson wrote:

On Friday, September 2, 2016 at 8:51:21 PM UTC-4, K leo wrote
Much easier to call C++ from Julia, particularly with the Cxx.jl package.   Performance-wise, it shouldn't matter, but it is always easier to write glue code in a higher-level language than in a lower-level language.

As far as I understand:

https://github.com/barche/CxxWrap.jl

should also be [as, not faster or slower] fast. Meaning runtime speed (of not development speed).

As I need neither, I've only looked a bit into, interactive C++ seems awesome in Cxx.jl, but is it fair to say the other package is [more] stable? Cxx.jl requires 0.5, that is just around the corner, I'm not sure the state then.

--
Palli.

Bart Janssens

unread,
Sep 6, 2016, 4:13:57 PM9/6/16
to julia...@googlegroups.com
On Tue, Sep 6, 2016 at 5:25 PM Páll Haraldsson <pall.ha...@gmail.com> wrote:

As far as I understand:

https://github.com/barche/CxxWrap.jl

should also be [as, not faster or slower] fast. Meaning runtime speed (of not development speed).

CxxWrap.jl actually has a slightly higher overhead: many calls are diverted to a C++ std::function, which has an inherent overhead. CxxWrap includes a benchmark (in the package test suite) where all elements of a 50000000-element Float64 array are divided by 2, using the function in the loop. Timings on Linux with julia0.5-rc3 are:
- Pure C++ and pure Julia are the same at 0.06 s
- ccall on a C function or a CxxWrap C++ function that can be called as a C function: 0.09 s
- CxxWrap function in the general case: 0.14 s

Normally Cxx.jl should be faster since it can inline in this case. However, I just tried adding it to the test and I get 2 s, which is way too high to be correct (I'll file an issue).

 
As I need neither, I've only looked a bit into, interactive C++ seems awesome in Cxx.jl, but is it fair to say the other package is [more] stable? Cxx.jl requires 0.5, that is just around the corner, I'm not sure the state then.


I just tried it, Cxx.jl installs after Pkg.checkout and Pkg.build on the rc3 binaries on Linux. The main difference with CxxWrap.jl is that Cxx.jl allows you to embed everything straight into Julia code, while in CxxWrap.jl all wrapping code is written in C++ and then loaded as a shared library into Julia. It is inspired by Boost.Python and provides a high-level interface specifically intended to expose C++ APIs in Julia. I'm not sure which is more stable, it highly depends on the application I think.

Cheers,

Bart

Páll Haraldsson

unread,
Sep 8, 2016, 9:31:38 AM9/8/16
to julia-users


On Tuesday, September 6, 2016 at 8:13:57 PM UTC, Bart Janssens wrote:


On Tue, Sep 6, 2016 at 5:25 PM Páll Haraldsson <pall.ha...@gmail.com> wrote:

As far as I understand:

https://github.com/barche/CxxWrap.jl

should also be [as, not faster or slower] fast. Meaning runtime speed (of not development speed).

CxxWrap.jl actually has a slightly higher overhead: many calls are diverted to a C++ std::function, which has an inherent overhead. CxxWrap includes a benchmark (in the package test suite) where all elements of a 50000000-element Float64 array are divided by 2, using the function in the loop. Timings on Linux with julia0.5-rc3 are:
- Pure C++ and pure Julia are the same at 0.06 s
- ccall on a C function or a CxxWrap C++ function that can be called as a C function: 0.09 s
- CxxWrap function in the general case: 0.14 s

Normally Cxx.jl should be faster since it can inline in this case.

Not sure I understand ("this case"), in another thread Tim Holy cautioned that C++ would not be inlined into Julia functions, as Julia functions can be.

[I understand you can debug Julia and C++ code, with Gallium, e.g. from one language to the next, that is across function boundaries.]

Tim Holy

unread,
Sep 8, 2016, 9:55:42 AM9/8/16
to julia...@googlegroups.com
On Thursday, September 8, 2016 6:31:37 AM CDT Páll Haraldsson wrote:
> Not sure I understand ("this case"), in another thread Tim Holy cautioned
> that C++ would not be inlined into Julia functions, as Julia functions can
> be.

My caution was for the opposite direction: you can't inline julia functions
into C++.

--Tim

Reply all
Reply to author
Forward
0 new messages