2017-02-20 48 views
1

Я использую понимание массива для определения интересующего значения для элементов массива определенного типа.Использование памяти памяти массива Julia

sum([value.interest for value in ArrayofMyType if condition]) 

Это само выражение находится в итеративном цикле. Это означает, что каждый цикл, это понимание использует новую память. Кроме того, условие каждый раз может налагать разные длины для результирующего массива, и определение предопределенного массива с фиксированной длиной вне цикла может быть не лучшим образом.

Это дает накладные расходы каждый раз, когда цикл работает, и я не знаю, как я могу сделать это более эффективным и лучше использовать память. Есть ли способ помочь мне в этом? Понимания стилистически удобны, но я думаю, что не самый эффективный в моем случае.

стиль кода является то, что:

for i in 1:MAX_ITER 
    ### Some code above 
    sum([value.interest for value in ArrayofMyType if condition])  
    ### Some code below 
end 

ответ

7

Вы можете использовать выражение генератора (только опустить скобки):

sum(value.interest for value in ArrayofMyType if condition) 

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

g = (value.interest for value in ArrayofMyType if condition) 

, чтобы создать такой объект вне вызова функции. Он реализует интерфейс итератора, в частности методы start, next, done и некоторые дополнительные методы, такие как length и могут поэтому использоваться везде, где итератор принимается.

Если все типа стабильный, накладные расходы по сравнению с ручной петлей являются приблизительно постоянными и незначительными для больших массивов. В противном случае накладные расходы могут быть большими.

Для коротких массивов, накладные расходы могут быть значимы и рукописный цикл может быть лучшим решением:

immutable A{T} x::T end 

const a = [A(i) for i in 1:100] 

mysum(a) = mysum(eltype(a), a) 

function mysum{T}(::Type{A{T}}, a) 
    sum = zero(T) 
    @inbounds for i in eachindex(a) 
     sum += a[i].x 
    end 
    return sum 
end 

using BenchmarkTools 

@benchmark sum(e.x for e in $a) 
@benchmark mysum($a) 

Это дает 50ns против 15ns на моем компьютере.

+0

Каков механизм этого? Создает ли массив? –

+3

Нет, он создает экземпляр типа «Генератор». Вы можете сделать 'g = (value.interest для значения в ArrayofMyType, если условие)', чтобы получить объект. Он реализует интерфейс итератора, например, функции 'start',' next' и 'done'. – tim

+1

@tim: вы можете добавить этот бит информации в свой ответ! – StefanKarpinski