Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Julia 抽象类型数组构造JIT性能_Julia - Fatal编程技术网

Julia 抽象类型数组构造JIT性能

Julia 抽象类型数组构造JIT性能,julia,Julia,在我的一个应用程序中,我必须在数组中存储不同子类型的元素,JIT的性能让我大吃一惊。 下面是一个简单的例子 abstract A immutable B <: A end immutable C <: A end b = B() c = C() @time getindex(A, b, b) @time getindex(A, b, c) @time getindex(A, c, c) @time getindex(A, c, b) @time getindex(A, b, c,

在我的一个应用程序中,我必须在数组中存储不同子类型的元素,JIT的性能让我大吃一惊。 下面是一个简单的例子

abstract A
immutable B <: A end
immutable C <: A end

b = B()
c = C()
@time getindex(A, b, b)
@time getindex(A, b, c)
@time getindex(A, c, c)
@time getindex(A, c, b)
@time getindex(A, b, c, b)
@time getindex(A, b, c, c);

  0.007756 seconds (6.03 k allocations: 276.426 KB)
  0.007878 seconds (5.01 k allocations: 223.087 KB)
  0.005175 seconds (2.44 k allocations: 128.773 KB)
  0.004276 seconds (2.42 k allocations: 127.546 KB)
  0.004107 seconds (2.45 k allocations: 129.983 KB)
  0.004090 seconds (2.45 k allocations: 129.983 KB)
在我的应用程序中,我面临许多不同的子类型:每个元素的类型都是
NTuple{N,a}
,其中
N
可以更改。因此,最终应用程序被困在JIT中

最好的办法是什么?我能想到的唯一方法是创建一个包装器,比如说
W
,然后在进入数组之前将我的所有元素装箱到
W
。因此编译器只编译数组函数一次

immutable W
    value::NTuple
end
多亏了@Matt B。在重载了他的
getindex
之后

c = C()
@time getindex(A, b, b)
@time getindex(A, b, c)
@time getindex(A, c, c)
@time getindex(A, c, b)
@time getindex(A, b, c, b)
@time getindex(A, b, c, c);

  0.008493 seconds (6.43 k allocations: 289.646 KB)
  0.000867 seconds (463 allocations: 19.012 KB)
  0.000005 seconds (5 allocations: 240 bytes)
  0.000003 seconds (5 allocations: 240 bytes)
  0.004035 seconds (2.37 k allocations: 122.535 KB)
  0.000003 seconds (5 allocations: 256 bytes)
而且,我意识到tuple的JIT实际上是相当有效的

@time tuple(1,2)
@time tuple(b, b)
@time tuple(b, c)
@time tuple(c, c)
@time tuple(c, b)
@time tuple(b, c, b)
@time tuple(b, c, c);
@time tuple(b, b)
@time tuple(b, c)
@time tuple(c, c)
@time tuple(c, b)
@time tuple(b, c, b)
@time tuple(b, c, c);

  0.000004 seconds (149 allocations: 10.183 KB)
  0.000011 seconds (7 allocations: 336 bytes)
  0.000008 seconds (7 allocations: 336 bytes)
  0.000007 seconds (7 allocations: 336 bytes)
  0.000007 seconds (7 allocations: 336 bytes)
  0.000005 seconds (7 allocations: 352 bytes)
  0.000004 seconds (7 allocations: 352 bytes)
  0.000003 seconds (5 allocations: 192 bytes)
  0.000004 seconds (5 allocations: 192 bytes)
  0.000002 seconds (5 allocations: 192 bytes)
  0.000002 seconds (5 allocations: 192 bytes)
  0.000002 seconds (5 allocations: 192 bytes)
  0.000002 seconds (5 allocations: 192 bytes)

这里的JIT启发式可能在基本库中进行更好的调优。虽然Julia默认为参数类型的唯一排列生成专门化方法,但有几个转义图案填充可用于减少专门化的数量:

  • 使用
    f(T::Type)
    而不是
    f{T}(::Type{T})
    。两者都是类型良好的,并且通过推理表现良好,但前者只能为所有类型生成一个方法

  • 使用未记录的所有大写字母
    g(::ANY)
    标志,而不是
    g(::ANY)
    。它在语义上是相同的,但是
    ANY
    将阻止该参数的专门化

在这种情况下,您可能希望专门化类型,而不是值:

  function Base.getindex{T<:A}(::Type{T}, vals::ANY...)
       a = Array(T,length(vals))
       @inbounds for i = 1:length(vals)
           a[i] = vals[i]
       end
       return a
   end

function Base.getindex{T这里的JIT启发式可能在基本库中得到更好的调整。虽然Julia默认为参数类型的唯一排列生成专门化方法,但有一些转义图案填充可用于减少专门化的数量:

  • 使用
    f(T::Type)
    而不是
    f{T}(::Type{T})
    。两者都是类型良好的,并且通过推理表现良好,但前者只为所有类型生成一个方法

  • 使用未记录的all caps
    g(::ANY)
    标志,而不是
    g(::ANY)
    。它在语义上是相同的,但是
    ANY
    将阻止该参数的专门化

在这种情况下,您可能希望专门化类型,而不是值:

  function Base.getindex{T<:A}(::Type{T}, vals::ANY...)
       a = Array(T,length(vals))
       @inbounds for i = 1:length(vals)
           a[i] = vals[i]
       end
       return a
   end

function Base.getindex{t如果我想编写一个函数
test(vals::ANY…)
,是否也可以断言
vals…
必须是
A
类型?否,据我所知,不在方法签名内。不过,您可以在方法体中这样做。在这种情况下,分配给
T
类型数组的元素将尝试转换任何非
A
值。如果没有定义转换。如果要编写函数
测试(VAL::ANY…)
,是否也可以断言
vals…
必须是
A
类型?否,据我所知,不在方法签名内。不过,您可以在方法体中这样做。在这种情况下,分配给
T
类型数组的元素将尝试转换任何非
A
值。如果没有定义转换。