2014-12-05 1 views
4

Я создал минимальный рабочий пример моего предыдущего вопроса (Julia allocates huge amount of memory for unknown reason), изолировав проблему. Это может быть непосредственно протестировано в REPL. Рассмотрим код:Вызов функции в @parallel приводит к огромным выделениям памяти

function test1(n) 
    s = zero(Float64) 
    for i = 1:10^n 
     s += sqrt(rand()^2 + rand()^2 + rand()^2) 
    end 
    return s 
end 

-

function test2(n) 
    @parallel (+) for i = 1:10^n 
     sqrt(rand()^2 + rand()^2 +rand()^2) 
    end 
end 

-

function test3(n) 
    function add(one, two, three) 
     one + two + three 
    end 

    @parallel (+) for i = 1:10^n 
     sqrt(add(rand()^2, rand()^2, rand()^2)) 
    end 
end 

Затем я проверить код:

@time test1(8); 
@time test1(8); 

@time test2(8); 
@time test2(8); 

@time test3(8); 
@time test3(8); 

А вот выход:

elapsed time: 1.017241708 seconds (183868 bytes allocated) 
elapsed time: 1.033503964 seconds (96 bytes allocated) 

elapsed time: 1.214897591 seconds (3682220 bytes allocated) 
elapsed time: 1.020521156 seconds (2104 bytes allocated) 

elapsed time: 15.23876415 seconds (9600679268 bytes allocated, 26.69% gc time) 
elapsed time: 15.418865707 seconds (9600002736 bytes allocated, 26.19% gc time) 

Может кто-то объяснить:

  • Почему первый запуск каждой функции выделять столько памяти?
  • Зачем стоит выделить выделение в test2(8)? test1(8)? Они делают то же самое.
  • Самое главное, что происходит с test3(8)? Он выделяет ОГРОМНЫЕ объемы памяти.

EDIT:

Julia Version 0.3.1 
Commit c03f413* (2014-09-21 21:30 UTC) 
Platform Info: 
    System: Darwin (x86_64-apple-darwin13.3.0) 
    CPU: Intel(R) Core(TM) i7-3615QM CPU @ 2.30GHz 
    WORD_SIZE: 64 
    BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Sandybridge) 
    LAPACK: libopenblas 
    LIBM: libopenlibm 
    LLVM: libLLVM-3.3 
+0

Это не происходит для меня. Что говорит 'versioninfo()'? – rickhg12hs

+0

@ rickhg12hs Отредактировано для добавления Julia version – Nick

ответ

2

В первом запуске каждой функции, распределение связано с процессом компиляции: помните, что большая часть JIT компилятором Джулии написано в Джулию, и поэтому любая память, которая получает потребляемая в процессе компиляции (в основном, анализ типов). Как только функция была скомпилирована, это распределение исчезает.

Для меня как test2, так и test3 выделяют около 50 тыс. Байт на 2-й прогон (с).

И, наконец, причина, по которой параллельные версии выделяют некоторую дополнительную память, связана с тем, как работает @parallel. Это в основном должно создать «thunk» из вашей функции и передать ее другим процессам. Этот thunk не прекомпилирован, потому что он может зависеть от переменных, которые вы передаете в качестве аргументов.

+0

Сколько времени займет test3 для вас и какая версия Julia вы используете? Я попробовал запустить его на версии 3.2 на Linux-машине, и у меня все еще есть 9600711508 байт, 24,90 секунд (намного дольше, чем test1 и test2) – Nick

+0

На моем старом и медленном ноутбуке с версией Julia версии 0.4.0-dev + 2043' и 'addprocs (2)', я получаю следующее: (вызов функции, приблизительное время (сек.), выделенные байты) -> [('test1 (8)', 9.8, 72), ('test2 (8)', 4.9 , ~ 32k), ('test3 (8)', 39, ~ 34k)] – rickhg12hs

+0

@Nick Попробуйте использовать свой код на [JuliaBox] (https://juliabox.org/). Никаких гигантских отчислений там не было. Это намного быстрее, чем мой ноутбук. – rickhg12hs