@everywhere не загружает функцию на мастер?

#parallel-processing #julia

#параллельная обработка #джулия

Вопрос:

Я создал модуль с условием if для количества ядер. Если количество ядер больше 1, маршрут параллельный; в противном случае он проходит последовательный маршрут, как показано в приведенном ниже коде

 module mymodule

import Pkg

using Distributed

if nworkers() > 1
    @everywhere using Pkg
    @everywhere Pkg.activate(".")
    @everywhere Pkg.instantiate()
    @everywhere using CSV
    @everywhere include("src/myfuncs.jl")

    function func()
        df=CSV.read(file);
        .......
    end

else
    using Pkg
    Pkg.activate(".")
    Pkg.instantiate()
    using CSV
    include("src/myfuncs.jl")
    function func()
        df=CSV.read(file);
        .......
    end
end
end #mymodule
  

1) Например, когда я создаю экземпляр сеанса Julia, julia -p 8 я получаю сообщение об ошибке ERROR: UndefVarError: CSV not defined . С другой стороны, когда экземпляр сеанса создается просто так julia , ошибки нет. Файлы Project.toml и Master.toml на один уровень выше, чем src . Должен ли я загружать на мастер перед использованием @everyone , например

 include("src/myfuncs.jl")
@everywhere include("src/myfuncs.jl")
  

2) Более того, я обнаружил, что когда программа переходит по последовательному маршруту, она не может найти myfunc.jl файл, потому что он уже находится в src папке (ищет src/src/myfunc.jl ), такое поведение меня смущает.

Может кто-нибудь поделиться своими мыслями здесь?

Ответ №1:

@everywhere выполняется для всех рабочих устройств и ведущего устройства. Однако:

  1. Иногда, если вам не повезло и импортируемый модуль не скомпилирован, может возникнуть состояние гонки (не всегда воспроизводимое, но сообщаемое несколькими пользователями в StackOverflow), поэтому лучше всего всегда писать код таким образом (обратите внимание, что если ваш кластер распределен по многим серверамэтого может быть недостаточно):

     using Distributed
    @everywhere using Distributed
    using CSV
    @everywhere using CSV
      
  2. Измените свой код, чтобы он выполнялся using до Pkg.activate

  3. Я не уверен, чего вы хотите достичь, @everywhere Pkg.instantiate() но уверен, что то, что вы делаете сейчас, не может быть хорошим (вы должны убедиться, что оно не выполняется более чем в одной копии для узла кластера)

  4. Наконец, нет необходимости разделять ваш код в зависимости от количества рабочих — см. Безопасный шаблон в пункте (1)

Надеюсь, это поможет!

Комментарии:

1. ваши предложения были полезны. Тем не менее, этот вопрос все еще беспокоит меня. include("myfuncs.jl"); @everywhere include("src/myfuncs.jl") — Работает только так, чем объясняется такое поведение?

2. Это точно такая же проблема с компиляцией. Вы хотите сначала скомпилировать код, а затем использовать его. В вашем вопросе вы также использовали другое местоположение для myfuncs.jl и src/myfuncs.jl — обычно этого не должно быть, если вы не выполняете пользовательский запуск подчиненных процессов или некоторые процессы не меняют местоположение своей домашней папки (например, с помощью cd функции)

3. Я не использовал другое местоположение для myfuncs.jl and src/myfuncs.jl . Я был «вынужден» использовать ее, потому что, как вы упомянули, похоже, что некоторые процессы меняют местоположение своей домашней папки (я не понимаю, почему это происходит?)

4. Кроме того, ваше предложение не разделять код в зависимости от количества рабочих было реализовано, и теперь оно работает нормально. Спасибо!

5. Что касается папок — я никогда не наблюдал их изменения, если вы не выполняете cd свой главный процесс перед запуском подчиненных процессов.