How to guarantee that using @Threads/@tspawnat will create threads that work on different Cores?

  • I am defining julia -t 2 before running my julia code which contains @Threads/@tspawnat to let some works run on the two threads. However, these two threads could be ruining on the same core and I am wondering if there is a way in julia to let the code works on a core not only thread.
    I tried to run julia with julia -p 2 -t 2 and not sure if this can solve what I want.
  • As I know threadid() can check the id of the working thread. And myid() can check the id of the working core, right?

The easiest option is to set the environment variable JULIA_EXCLUSIVE=1. If you want more explicit control (and if you’re on linux) you can use ThreadPinning.jl.

2 Likes

Note that the -p option (and also myid()) is for multiprocessing (while -t is for multithreading) I would assume that you don’t want to mix both parallelisation variants. Hence, you should drop the -p 2 part.

1 Like

No. It indicates the id of a worker process (when using multiprocessing).

1 Like
  • Could you please tell me how to set JULIA_EXCLUSIVE=1 if I am using VS Code?
  • I am working on windows, does ThreadPinning.jl. only work in linux?
  • what is function in julia to know the core id?
  • It seems that I dont know the difference between threads, processes and cores. Could you please give me a bit explanatins?

As Carsten Bauer says. Also, myid() gets you the process number, nothing about what core it’s running on. Without setting any environment variables, Julia will let the operating system schedule the threads, which will generally do what you want. Just run a job and watch your CPU meters, and you’ll see that the OS is using the available cores.

1 Like

I assume you want to use the integrated REPL from the Julia VSCode extension? In this case, I’m not sure but would assume that putting JULIA_EXCLUSIVE=1 julia under the Julia.executable setting (or similar) should work.

Alternatively, should can set the environment variable globally. Should be straightforward to google.

Currently yes. There is a rudimentary PR for Windows support but it’s pretty stale.

  • Yes.
  • So, if I want to run julia from command window, I should write julia -t 2 JULIA_EXCLUSIVE=1 which gives error?

The other way around: JULIA_EXCLUSIVE=1 julia -t 2

1 Like

Writing that gave me:

JULIA_EXCLUSIVE=1 : The term 'JULIA_EXCLUSIVE=1' is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
At line:1 char:1
+ JULIA_EXCLUSIVE=1 julia -t 2
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (JULIA_EXCLUSIVE=1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Hm, ok, maybe this only works on Linux. In any case, it should be easy to google how to set environment variables on Windows. I think you can do it in two steps

set JULIA_EXCLUSIVE=1
julia -t 2

But it’s been a while since I’ve last touched a Windows machine. So I’m not the best person to help you further.

1 Like

Thank you!
I wrote that and I did not get errors. So, if I want to double check that the JULIA_EXCLUSIVE=1 is set correctly, what is the command/function that I have to put in Julia REPL? I put in the REPL

julia> ENV["JULIA_EXCLUSIVE"]
ERROR: KeyError: key "JULIA_EXCLUSIVE" not found`

There is no built-in function for this (AFAIR) but you can define

const kernel32 = "kernel32"
get_current_processor_number() = @ccall kernel32.GetCurrentProcessorNumber()::Culong

Calling this function on the threads (e.g. with @tspawnat) should give you the desired processor id.

1 Like

I wrote the below test MWE, however, I got error. Is the location of const kernel32 = "kernel32" wrong?

function f()
  const kernel32 = "kernel32"
          thrs = [@tspawnat i begin
                  println("Thread $(threadid()) ")
                  get_current_processor_number() = @ccall kernel32.GetCurrentProcessorNumber()::Culong
          end for i = 2:nthreads()];

          # Main Thread
          println("Thread $(threadid()) ")
          get_current_processor_number() = @ccall kernel32.GetCurrentProcessorNumber()::Culong
  fetch.(thrs);
  return nothing
end
f()
ERROR: LoadError: syntax: unsupported `const` declaration on local variable around C:\pathtofile\tt.jl

This should do it (written it down without testing it):

const kernel32 = "kernel32"
get_current_processor_number() = @ccall kernel32.GetCurrentProcessorNumber()::Culong

Threads.@threads :static for i in 1:Threads.nthreads()
    procid = get_current_processor_number()
    println("Thread: $i, Processor: $procid")
end
1 Like

Thank you very much!
I followed and I got

Thread: 1, Processor: 5
Thread: 2, Processor: 7

However, my computer has only 6 physical cores as shown below. And I am wondering why I got proccessor: 7

julia> versioninfo()
Julia Version 1.8.5
Commit 17cfb8e65e (2023-01-08 06:45 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 12 × Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, skylake)
  Threads: 2 on 12 virtual cores

Moreover, I run julia without setting JULIA_EXCLUSIVE=1 and then run your code and I got similar results such as below. So, I did not realize the difference.

Thread: 2, Processor: 9
Thread: 1, Processor: 5

Do you happen to have multiple processors in your system? Also does your system have hyperthreading?

1 Like

Yes and I can see the multiple CPUs (12) in the Task Manager and when I write versioninfo() it gives:

Julia Version 1.8.5
Commit 17cfb8e65e (2023-01-08 06:45 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 12 × Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, skylake)
  Threads: 2 on 12 virtual cores