Используйте многопоточность для функции прокатки - PullRequest
3 голосов
/ 20 марта 2020

У меня есть некоторая скользящая функция, которая оценивает массив в соответствии с функцией, например,

rolling(x, func, window=10) = [func(x[1+i:window+i+1]) for i in 0:(length(x)-window-1)]

для среднего значения:

julia> using Statistics

julia> rolling(1:10,mean,5)
5-element Array{Float64,1}:
 3.5
 4.5
 5.5
 6.5
 7.5

Интересно, было ли это просто и быстро? и безопасный способ распараллелить эту функцию?

1 Ответ

2 голосов
/ 21 марта 2020

Вот оно. Обратите внимание, что для mean это можно сделать по-другому из-за его свойств качения. Производительность также будет отличаться. Для меньших циклов иногда может быть лучше @simd (сильно зависит от реального сценария. Поэтому считайте это отправной точкой.


using Statistics

rolling0(x, func, window=10) = [func(@view x[1+i:window+i+1]) for i in 0:(length(x)-window-1)]

function rolling(x, func, window=10)
    res = Vector{Float64}(undef, length(x)-window)
    Threads.@threads for i in 1:(length(x)-window)
        @inbounds res[i] = func(@view x[i:i+window]) 
    end
    res
end

z = rand(10000)
@assert rolling0(z,mean) == rolling(z,mean)
using BenchmarkTools

Тесты:

julia> @btime rolling0($z, mean);
  104.601 μs (9994 allocations: 546.48 KiB)

julia> @btime rolling($z, mean);
  48.100 μs (10021 allocations: 549.88 KiB)
...