Embedding Julia into multithreading apps

I have an multithreading application. I want to embed “Julia” into it so that it can be accessed from any thread. There are many questions:

  • whether you need to protect calls through CriticalSection or Mutex
  • is there a built-in mechanism for determining whether or not Julia is busy
  • what initialization to do in each thread
  • how to work with Garbage Collector

I will be grateful for the answers and links to practical examples.

Julia is not thread safe. That should actually answer all your question. Make a “Julia executer” thread that can accept jobs, one at a time. Then you can also see whether Julia is busy (if your thread is busy, i.e. indicates that is runs a job).

It is thread safe but does not support external threads

what is thread safe? thread safe means that any of the public API functions can be called simultaneously from different threads. I doubt that this is possible (e.g. that 5 threads call jl_init simultaneously. Its some time that I wrote the embedding example but at that time where I initially did that Julia was certainly not thread safe.

Are there plans to make Julia support external threads? So that we can have multiple Julia instances like we can do with Lua.

No. Thread safe means that the runtime functions can be called from multiple threads. It does not mean all functions can be called like that and it does not mean that there’s no limit what so ever on when and how many times you can call any functions. Calling julia non-threadsafe makes as little sense as calling libc non-threadsafe. Sure, there are some functions in either that should not be called from multiple threads, but those are the functions that are never intended to be so it’s not a useful definition. In particular, in the libc case it does not mean you cannot use it in multi-threaded applications and in the julia case, it does not mean you can’t interact with multiple julia threads in C code.

And just to be extra clear, for the example you give, in particular, jl_init isn’t thread safe simply because it does not support being run multiple times. This is a completely orthogonal requirement with multithreading. Even when external thread support is added (i.e. you can “access it from any thread”) this is unlikely to change, or at least unlikely to change because such support.

In another word, for your definition, julia will never ever be thread safe, neither is libc, which is fine if you define it as such but I doubt it’s very useful. For a more useful definition of whether a majority part that is intended to be used by multiple threads is well synchronized, then yes for both libc and julia. (Of course there can be and probably is bug, but at least that’s the specification.)

3 Likes

Those are two orthogonal requests. Both can in principle be done without the other.

Supporting external threads is likely. Having multiple instances is not.

3 Likes

In the mean time, something like this https://gist.github.com/cdsousa/473463e9b4e4f57c5b598e6966ca6a21 can be used to partially workaround the current limitations.

1 Like

The meaning of the term “thread safe” certainly varies depending on the context that it is being used.

So can I quote you with this statement:
“The julia embedding C API is thread safe”

Because this is what the OP asked about. It was not asked if Julia internally is thread safe, it was asked about embedding of Julia.

And yes libc is of course not fully thread safe but only partially. Have a look here

http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_01

you can find that there are various functions defined in the POSIX standard that are not required to be thread safe.

My statement “Julia is not thread safe” might have been to generic but let me rephrase that:

“The public Julia embedding API is not fully thread safe. There might be functions that are thread safe but those are not documented and marked as such. Therefore it is recommend as a user of the API to prevent concurrent accesses to Julia API functions.”

1 Like

Yes.

No. he is from the start just not even asking about only the thread safety at all. He is asking about the thread related limitation on the API. There are much more (thread related) properties on the API then what you can cover with just “threadsafety”.

Still wrong.

Pretty much the only function that is not meant to be threadsafe is the init functions, which cannot be called from multiple thread for reasons completely unrelated to threading as explained above. The only limitations are,

  1. It’s pretty much still experimental since we know there’s bug but almost all functions are meant to be threadsafe, if only for the reason that pretty much all of those functions are called by julia itself from multiple threads. This is why it may not be fully documented/marked.

  2. Extenal thread is not supported, which is a limitation that’s fairly orthogonal to the general meaning of “threadsafe”.

Again, there are multiple tiers of thread safety. Calling it “not thread safe” means it doesn’t even have a basic level of thread support and julia’s embedding API is well passed that. I take this meaning from your word since you are using it to imply that “Therefore it is recommend as a user of the API to prevent concurrent accesses to Julia API functions”, which is just wrong. Concurrent access of julia API function is no less supported or recommended than using multiple threads in julia itself.

And yes, it’s way too generic. That’s exactly what I’m complaining about because it’s misleading and have led you to the wrong conclusion. You can say jl_init is not thread safe, which at least isn’t wrong even though the reason is largely irrelevant to thread… Or better you should say it doesn’t support external thread, which is the actual limitation.

1 Like

define what you mean with “external thread”.

Thread external to Julia, I.e those that are not the Julia main thread and isn’t started by Julia.

(usually I’ll say unmanaged, I just use external since I felt like it could be easier for someone not knowing Julia internal to understand)

We are talking about embedding here. So lets say I start two pthreads. One of that calls jl_init. Is it ok that the two thread call jl_* (except j_init) concurrently after that?

1 Like

No, because the other thread is not managed by julia.

Not sure what you are getting at here but just to be clear, I’ve never said that what he want to do is possible or safe to do. As said above, I was only correcting,

Since thread safety isn’t his question. and now

Since calling from multiple managed thread is still concurrent access and it’s supported.

read: any thread.

You have an interesting definition that the Julia API is thread safe because it is allowed to use it concurrently from a certain subsets of all threads. I am a lot more conservative and would call an API as long “not-thread” safe as it cannot be used by any thread (and not managed ones). The OP has certainly not talked about managed threads and this was what my answer was targeting.

But anyway, lets agree to disagree here. Would be interesting what the official statement of e.g. @jeff.bezanson is.

1 Like

Read: not “thread safety”.

You have an interesting definition that the julia API is not thread safe even though it is safe to call them concurrently. From the very start I called out the limitation on top of the thread safety.

And you have a definition that assume anything that’s thread related is called thread-safety. That’s simply not the case.

Which is fine, just that the it’s not about thread safety.

I did from the very start, with my own opinion on it that you don’t have to agree for sure:

edit: also note that I said it’s not useful. I didn’t say it’s wrong. (It’s not the same as mine which certainly isn’t wrong). It’s not useful because

(or julia C-API is not thread safe) isn’t a statement that can

Given that, I was only arguing about the definition being misleading and in particular due to the wrong conclusion you’ve drawn from it. i.e., claiming that

is just wrong.

As long as you replace your thread-safe with safe for external/unmanaged/arbitray thread (since it’s misleading) and be clear that you only need to prevent access from those thread rather than any concurrent access (since this statement is just wrong) I have no problem with whatever definition you use.

And just for the record, I do agree saying that julia is fully thread-safe is just as misleading, which is why I never say that (“fully”) and always make sure I mention the limitation on external/managed thread at the same time (as long as I remember) in context that unmanaged thread is of any relanvance.

I am out. I am here to help people and not argue with you whether “thread safe” == “fully thread safe”.

1 Like

@yuyichao

I have interest on that because my satellite simulator uses Qt and letting julia on external thread to Qt would help a lot.

I am very unfamiliar with the terms, but can you explain me something: if I start julia on an external pthread, then can I submit jobs from another pthread to the former? Something like @cdsousa showed us? Is it safe and advisable?

Btw, thanks @cdsousa for this very good example, it will save me some hours :slight_smile:

Then don’t make wrong statement (about calling julia C API concurrently being not recommended). That does not help people.

As I said, as long as you don’t simply say julia or julia’s C API is not thread safe without specifying which specific part isn’t, it doesn’t matter what definition you use. Claiming it being not thread safe and stop there, which is what you did, will certainly make people think any use of thread is not supported with the julia C API.

Not through julia, because (julia)

Again, just don’t simply call this “not thread safe”. That’s a pretty useless and even harmful statement about the current state of threading support.

1 Like