繁体   English   中英

`UnitRange` 和 `Array` 有什么区别?

What is the difference between `UnitRange` and `Array`?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我有两个版本的代码似乎做同样的事情:

sum = 0
for x in 1:100
    sum += x
end
sum = 0
for x in collect(1:100)
    sum += x
end

两种方法之间有实际区别吗?

2 个回复

UnitRange将使用常量空间,而Array将与您正在迭代的元素数量成比例地增长。

您可以使用BenchmarkTools package 查看差异。

julia> @btime sum(1:1000000)
  0.044 ns (0 allocations: 0 bytes)
500000500000

julia> @btime sum(collect(1:1000000))
  1.123 ms (2 allocations: 7.63 MiB)
500000500000

两种方法在空间和时间性能上都存在显着差异。 UnitRange避免了在您一次不需要时分配一大块 memory 的工作。 如果可能,更喜欢使用UnitRange而不是Array

在 Julia 中, 1:100返回一个名为UnitRange的特定结构,如下所示:

julia> dump(1:100)
UnitRange{Int64}
  start: Int64 1
  stop: Int64 100

这是一个非常紧凑的结构,用于表示具有步骤 1 和任意(有限)大小的范围。 UnitRangeAbstractRange的子类型,是表示具有任意步长的范围的类型,是AbstractVector的子类型。

每当您使用getindex (或语法糖vector[index] )时, UnitRange的实例都会动态计算它们的元素。 例如,使用@less (1:100)[3]你可以看到这个方法:

function getindex(v::UnitRange{T}, i::Integer) where {T<:OverflowSafe}
    @_inline_meta
    val = v.start + (i - 1)
    @boundscheck _in_unit_range(v, val, i) || throw_boundserror(v, i)
    val % T
end

这是通过将i - 1添加到范围的第一个元素( start )来返回向量的第i个元素。 一些函数使用UnitRange优化了方法,或者更普遍地使用AbstractRange 例如,使用@less sum(1:100)您可以看到以下内容

function sum(r::AbstractRange{<:Real})
    l = length(r)
    # note that a little care is required to avoid overflow in l*(l-1)/2
    return l * first(r) + (iseven(l) ? (step(r) * (l-1)) * (l>>1)
                                     : (step(r) * l) * ((l-1)>>1))
end

此方法使用算术级数之和的公式,该公式非常有效,因为它是在与向量大小无关的时间内进行评估的。

另一方面, collect(1:100)返回一个包含一百个元素 1、2、3、...、100 的普通Vector 。与UnitRange (或其他类型的AbstractRange )的主要区别在于getindex(vector::Vector, i) (或vector[i] ,带有vector::Vector )不进行任何计算,而只是访问向量的第i个元素。 Vector优于UnitRange的缺点是,一般来说,在使用它们时没有有效的方法,因为这个容器的元素是完全任意的,而UnitRange表示一组具有特殊属性(排序、恒定步长等)的数字。 ..)。

如果您比较UnitRange具有超高效实现的方法的性能,这种类型将胜出(注意使用BenchmarkTools中的宏时使用$(...)对变量进行插值):

julia> using BenchmarkTools

julia> @btime sum($(1:1000_000))
  0.012 ns (0 allocations: 0 bytes)
500000500000

julia> @btime sum($(collect(1:1000_000)))
  229.979 μs (0 allocations: 0 bytes)
500000500000

请记住,每次使用getindex访问元素时, UnitRange都会带来动态计算元素的成本。 例如考虑这个 function:

function test(vec)
    sum = zero(eltype(vec))
    for idx in eachindex(vec)
        sum += vec[idx]
    end
    return sum
end

让我们用一个UnitRange和一个普通的Vector对其进行基准测试:

julia> @btime test($(1:1000_000))
  812.673 μs (0 allocations: 0 bytes)
500000500000

julia> @btime test($(collect(1:1000_000)))
  522.828 μs (0 allocations: 0 bytes)
500000500000

在这种情况下,调用普通数组的 function 比使用UnitRange的更快,因为它不必动态计算 100 万个元素。

当然,在这些玩具示例中,迭代vec的所有元素而不是它的索引会更明智,但在现实世界的情况下,这样的情况可能更明智。 然而,最后一个示例表明UnitRange不一定比普通数组更有效,尤其是当您需要动态计算其所有元素时。 当您可以利用可以在恒定时间内执行操作的专用方法(如sum )时, UnitRange会更有效。

作为文件备注,请注意,如果您最初有UnitRange ,将其转换为普通Vector以获得良好性能不一定是一个好主意,特别是如果您只使用一次或很少使用它,因为转换到Vector涉及范围内所有元素的动态计算和必要 memory 的分配:

julia> @btime collect($(1:1000_000));
  422.435 μs (2 allocations: 7.63 MiB)

julia> @btime test(collect($(1:1000_000)))
  882.866 μs (2 allocations: 7.63 MiB)
500000500000
1 Julia中的UnitRange类型是什么意思?

我尝试阅读具有OOP强类型背景的Julia代码 。 我得到了大部分,但是UnitRange{Int}; 它的使用方式对我来说并不清楚:它是一个数组还是一个整数? 任何人都可以在一些强类型语言中UnitRange类型的模拟吗? ...

2018-08-13 21:13:06 1 457   julia
2 Array和Array()有什么区别?

我可以这样声明一个数组: 或因此: 但是,只能将第一个作为这样的参数传递: 第二个是这样的: 您可以使用第二个命令执行此操作: 但不是第一个。 第一种方法声明的变量数组与第二种方法声明的变量数组有什么区别? 它们都是相同的vartype() - ...

4 数组和列表有什么区别

当我看到有人使用数组而其他人使用列表时,我在堆栈溢出中四处徘徊以寻求问题,我想知道列表和数组之间的区别是什么。 ...

6 切片和数组之间有什么区别?

为什么两个&amp;[u8]和&amp;[u8; 3] &amp;[u8; 3]这个例子好吗? &amp;[T; n] &amp;[T; n]可以强迫&amp;[T]是使它们可以容忍的方面。 - 克里斯摩根 为什么可以&amp;[T; n] &amp;[T; n]强 ...

8 JSON 和 Array 有什么区别?

JSON 和 Array 有什么区别? 他们为什么称 JSON 对象和数组对象。 http://wiki.appcelerator.org/display/guides/Using+TableViews+-+data.js 这是一个数组还是 JSON? 我如何识别? ...

9 生成器和数组有什么区别?

今天PHP团队发布了PHP 5.5.0版本,其中包括对生成器的支持。 阅读文档 ,我注意到它完全可以用数组做。 PHP团队生成器示例 : 结果 : 但我可以使用数组做同样的事情。 我仍然可以保持与早期版本的PHP兼容。 看看 : 所以问题是 :这个新功能的 ...

10 ArrayBuffer和Array有什么区别

我是scala / java的新手,我在解决这两个问题上遇到了麻烦。 通过阅读scala 文档,我了解到ArrayBuffer是交互式的(追加,插入,前置等)。 1)基本的实施差异是什么? 2)这两者之间是否存在性能差异? ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM