Эффективное перебирание структур в Julia

#julia

#julia

Вопрос:

У меня простой вопрос. Я определил структуру, и мне нужно инициализировать их много (порядка миллионов) и перебирать их.

Я инициирую по одному и выполняю цикл следующим образом:

 using Distributions

mutable struct help_me{Z<:Bool}
    can_you_help_me::Z
    millions_of_thanks::Z
end

for i in 1:max_iter
    tmp_help = help_me(rand(Bernoulli(0.5),1)[1],rand(Bernoulli(0.99),1)[1])
    # many follow-up processes 
end
 

Распределение памяти увеличивается в max_iter. Для моей цели мне не нужно сохранять каждую структуру. Есть ли способ «повторно использовать» выделение памяти, используемое структурой?

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

1. Вопрос 1: зачем вы это делаете Z<:Bool ? Bool это уже конкретный тип? Вопрос 2: какая-либо причина help_me должна быть mutable ? неизменяемые структуры часто дешевле. кроме rng того, явная передача в rand может дать вам простое ускорение в 2 раза. (из-за соображений безопасности многопоточности)

2. Привет, Osca, спасибо за вопросы. 1. Не знал. Спасибо. 2. Это может быть не так на самом деле. Спасибо. Я все еще разрабатываю процессы, которые должен пройти каждый агент. 3. Не знал. Спасибо. Есть ли решение проблемы выделения памяти?

3. Я думаю, что создание структуры не mutable исправит это. неизменяемые объекты могут быть выделены стеком (в большинстве случаев), поэтому их создание и уничтожение должны быть в основном бесплатными.

Ответ №1:

Ваша основная проблема заключается здесь:

 rand(Bernoulli(0.5),1)[1], rand(Bernoulli(0.99),1)[1]
 

Вы создаете массив длиной 1, а затем считываете первый элемент из этого массива. Это выделяет ненужную память и требует времени. Не создавайте здесь массив. Вместо этого напишите

 rand(Bernoulli(0.5)), rand(Bernoulli(0.99))
 

Это просто создаст случайные скалярные числа, а не массив.

Сравните тайминги здесь:

 julia> using BenchmarkTools

julia> @btime rand(Bernoulli(0.5),1)[1]
  36.290 ns (1 allocation: 96 bytes)
false

julia> @btime rand(Bernoulli(0.5))
  6.708 ns (0 allocations: 0 bytes)
false
 

в 6 раз быстрее и без выделения памяти.

Похоже, это общая проблема. Очень часто я вижу, как люди пишут rand(1)[1] , когда они должны использовать just rand() .

Кроме того, подумайте, действительно ли вам нужно создавать структуру mutable , как упоминали другие.

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

1. Спасибо. Очень признателен.

Ответ №2:

Если структура больше не нужна (т. Е. Нигде не упоминается за пределами текущей итерации цикла), сборщик мусора автоматически освободит свою память, если потребуется.

В противном случае я согласен с предложениями Оскара Смита: выделение памяти и сборка мусора требуют времени, избегайте этого по соображениям производительности, если это возможно.