При решении Задачи 10 от Project Euler вручную (вместо простого using Primes
) я реализовал наивное сито эратосфена в Юлии, используя BitVector
.Он выдает правильный вывод, но когда я проверил его стабильность типов с помощью @code_warntype
, я обнаружил, что i
выделяется как Core.Box
, что влияет на тип psum
, и это, в свою очередь, приводит к стабильности типався функция прочьИспользуемый код:
function primesum(limit::T = 2_000_000) where T<:Integer
#easy way: using Primes; sum(primes(limit))
#hard way:
is_prime_num = BitVector(limit)
is_prime_num .= true
psum = zero(limit)
for i in 2:limit
if is_prime_num[i]
psum += i
multiples_of_i = [k*i for k in 2:(limit÷i)]
is_prime_num[multiples_of_i] .= false
end
end
psum
end
А вот часть Variables вывода code_warntype
(полный вывод здесь ):
Variables:
#self#::#primesum
limit::Int64
#46::##46#47
i::Core.Box
multiples_of_i::Any
#temp#@_6::Int64
is_prime_num::BitArray{1}
psum::Any
J::Any
#temp#@_10::Any
В целом,многие типы в коде (включая тип возвращаемого значения функции) оставляются либо Any
, либо типом where _
.
Мне удалось улучшить скорость (почти в 10 раз) и память (~ 3 раза), изменив строку цикла for
на for i::T in 2:limit
- тогда i
по-прежнему устанавливается как Core.Box
, ноон получает typeassert
ed для Int64 и не распространяет нестабильность на psum
и другие.Но Меня больше интересует, почему Джулия не может вывести тип i
, чем ускорить этот конкретный код. Я привык набирать нестабильности, что имеет смысл, по крайней мере, в ретроспективе, но этоткажется довольно ясным и простым для вывода, поэтому я хотел бы знать, где здесь присутствует неоднозначность типов.