Why rank 0 cannot receive stdin input?

using MPI

input_channel = Channel{String}(1)
test = Ref(false)

function listen_for_input()
    @async begin
        println("Rank 0: Listening for input...")
        while true
            input = readline(stdin)
            println("Rank 0: Read input: $input")
            put!(input_channel, input)
        end
    end
end

function main_task()
    i = 0
    global test
    rank = MPI.Comm_rank(MPI.COMM_WORLD)
    println("Starting main task on rank $rank")

    while true
        input = nothing
        if rank == 0
            println("Rank 0: Iteration $i")
            if isready(input_channel)
                input = take!(input_channel)
                println("Rank 0: Received input: $input")
            end
            if input == "save"
                test[] = true
                println("Rank 0: Setting test to true")
            end
        end
        i += 1
        MPI.Bcast!(test, 0, MPI.COMM_WORLD)
        for j = 0:MPI.Comm_size(MPI.COMM_WORLD) - 1
            if MPI.Comm_rank(MPI.COMM_WORLD) == j
                println("Rank $j: test[] = $(test[])")
            end
            MPI.Barrier(MPI.COMM_WORLD)
        end
        sleep(1)
    end
end

MPI.Init()
if MPI.Comm_rank(MPI.COMM_WORLD) == 0
    listen_for_input()
end
main_task()

I’m wondering why it cannot work with command mpiexecjl --project=. -n 4 julia ./test.jl, even with the parameter-n 1… It works correctly on single core by julia --project=. ./test.jl.

mpiexecjl is a shell script that runs a Julia script that runs mpiexec to launch your Julia program. I wonder if this is too many levels of indirection for stdin to get piped through?

You might try using mpiexec directly. Run MPI.mpiexec() in Julia to find the mpiexec (or equivalent) program invocation. Then run it in your shell with JULIA_PROJECT=. <mpiexec command> -n 4 julia ./test.jl

2 Likes

Ah, yeah, it works with mpiexec -n 4 julia --project=. ./test.jl. It helps a lot. Thanks!

I don’t have the time to investigate this further now, but I have the feeling it should be doable. For example, this simplified script, which doesn’t involve using an MPI launcher, can read stdin correctly:

#!/bin/sh

julia -e 'run(pipeline(`$(Base.julia_cmd()) $(ARGS)`; stdout, stderr))' -- "${@}"
% ./test.sh -e 'print("Write something: "); println("You wrote: ", readline(stdin))'
Write something: hello world
You wrote: hello world

I’ll need to see where stdin is getting lost in mpiexecjl, but that’s only one extra level of indirection than the script above.