Size: a a a

Язык программирования Julia / Julia programming language

2020 May 25

A

Alexandr in Язык программирования Julia / Julia programming language
Как я понимаю тут проблема не столько в ntuple сколько в лямбде
источник

АО

Андрей Оськин... in Язык программирования Julia / Julia programming language
Ну да.
Альтернативно можно аннотировать, что ты гарантируешь возвращаемый тип. Тогда он может сможет использовать эту информацию.
источник

A

Alexandr in Язык программирования Julia / Julia programming language
julia> const funs2 = (x -> x^2, x -> x^3)
julia> @code_warntype ntuple(i -> funs2[i](1), Val(2))
Variables
 #self#::Core.Compiler.Const(ntuple, false)
 f::Core.Compiler.Const(var"#43#44"(), false)
 #unused#::Core.Compiler.Const(Val{2}(), false)

Body::Tuple{Int64,Int64}
1 ─      nothing
│   %2 = (f)(1)::Core.Compiler.Const(1, false)
│   %3 = (f)(2)::Core.Compiler.Const(1, false)
│   %4 = Core.tuple(%2, %3)::Core.Compiler.Const((1, 1), false)
└──      return %4
источник

A

Alexandr in Язык программирования Julia / Julia programming language
В репле переменные не типизированные, собственно поэтому он Any и возвращает - он не знает тип funs. С const все нормально определяется
источник

АО

Андрей Оськин... in Язык программирования Julia / Julia programming language
А, хорошее замечание, да.
источник

A

Alexandr in Язык программирования Julia / Julia programming language
Кстати, посмотрел тут - вызов ntuple(f, n) c n до 10 включительно прямо руками мапиться в создание tuple без всякой магии: https://github.com/JuliaLang/julia/blob/f12cde0e8c7f4268838d3201dd9e13b90ea44633/base/ntuple.jl
источник

A

Alexandr in Язык программирования Julia / Julia programming language
function ntuple(f::F, n::Integer) where F
   t = n == 0  ? () :
       n == 1  ? (f(1),) :
       n == 2  ? (f(1), f(2)) :
       n == 3  ? (f(1), f(2), f(3)) :
       n == 4  ? (f(1), f(2), f(3), f(4)) :
       n == 5  ? (f(1), f(2), f(3), f(4), f(5)) :
       n == 6  ? (f(1), f(2), f(3), f(4), f(5), f(6)) :
       n == 7  ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7)) :
       n == 8  ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8)) :
       n == 9  ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9)) :
       n == 10 ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10)) :
       _ntuple(f, n)
   return t
end
источник

A

Alexandr in Язык программирования Julia / Julia programming language
Так что при любых вопросах с ntuple можно просто проверять что происходит с созданием руками (f(1), f(2)) и делать выводы
источник

VG

Viktor G. in Язык программирования Julia / Julia programming language
странно, что только до 10, в других источниках говорили, что туплы оптимизированы под размер до 32 элементов включительно
источник

A

Alexandr in Язык программирования Julia / Julia programming language
Дальше надо смотреть как _ntuple устроен...
источник

A

Alexandr in Язык программирования Julia / Julia programming language
А, ну собственно
function _ntuple(f, n)
   @_noinline_meta
   (n >= 0) || throw(ArgumentError(string("tuple length should be ≥ 0, got ", n)))
   ([f(i) for i = 1:n]...,)
end

Возможно я ошибаюсь, но мне кажется единственная разница в том, что тут будет аллокация массива при создании
источник
2020 May 26

VG

Viktor G. in Язык программирования Julia / Julia programming language
оптимизирует, если для значений n > 10 задана как Val(n):
const y = x->sin(x)
@time t = ntuple(y, Val(10)) # 0.000001 seconds (1 allocation: 96 bytes)          
@time t = ntuple(y, Val(11)) # 0.000001 seconds (1 allocation: 96 bytes)          
@time t = ntuple(y, 10)      # 0.000001 seconds (1 allocation: 96 bytes)        
@time t = ntuple(y, 11)      # 0.000011 seconds (15 allocations: 512 bytes)
источник

VG

Viktor G. in Язык программирования Julia / Julia programming language
похоже на какое-то недоисправление для тех, кто не хочет писать Val(n), но только при малых n
источник

VG

Viktor G. in Язык программирования Julia / Julia programming language
хотя это может быть связано со скоростью компиляции для больших n
источник

A

Alexandr in Язык программирования Julia / Julia programming language
Да, увидел. Действительно для Val отдельные методы создания:
ntuple(f, ::Val{0}) = ()
ntuple(f, ::Val{1}) = (@_inline_meta; (f(1),))
ntuple(f, ::Val{2}) = (@_inline_meta; (f(1), f(2)))
ntuple(f, ::Val{3}) = (@_inline_meta; (f(1), f(2), f(3)))

@inline function ntuple(f::F, ::Val{N}) where {F,N}
   N::Int
   (N >= 0) || throw(ArgumentError(string("tuple length should be ≥ 0, got ", N)))
   if @generated
       quote
           @nexprs $N i -> t_i = f(i)
           @ncall $N tuple t
       end
   else
       Tuple(f(i) for i = 1:N)
   end
end
источник

VG

Viktor G. in Язык программирования Julia / Julia programming language
Что-то я не понял роль
if @generated
- проверяет, смог ли сгенерировать код?
источник

A

Alexandr in Язык программирования Julia / Julia programming language
Нет, там все сложнее. Как я понял доку в таком варианте компилятор может решать использовать ли ему ветку с @generated, или нет
источник

A

Alexandr in Язык программирования Julia / Julia programming language
In this style of definition, the code generation feature is essentially an optional optimization. The compiler will use it if convenient, but otherwise may choose to use the normal implementation instead. This style is preferred, since it allows the compiler to make more decisions and compile programs in more ways, and since normal code is more readable than code-generating code. However, which implementation is used depends on compiler implementation details, so it is essential for the two implementations to behave identically.
источник
2020 May 27

RS

Roman Samarev in Язык программирования Julia / Julia programming language
источник

АО

Андрей Оськин... in Язык программирования Julia / Julia programming language
О, слак.
Надо куда-то перетащить, а то пески времени быстро утянут эту ссылку
источник