- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在数组 X 中搜索所需的模式(变量模板)。模板的长度为 9。
我正在做类似的事情:
function check_alloc{T <: ZeroOne}(x :: AbstractArray{T}, temp :: AbstractArray{T})
s = 0
for i in 1 : 1000
myView = view(x, i : i + 9)
if myView == temp
s += 1
end
end
return s
end
并在这个短循环中获得意外的内存分配(46 KB)。为什么会发生这种情况以及如何防止内存分配和性能下降?
最佳答案
您获得分配的原因是 view(A, i:i+9)
创建一个名为 SubArray
的小对象。这只是一个“包装器”,本质上存储对 A
的引用。以及您传入的索引 ( i:i+9
)。由于包装器很小(一维对象约为 40 字节),因此有两种合理的选择来存储它: on the stack or on the heap 。 “分配”仅指堆内存,因此如果 Julia 可以将包装器存储在堆栈上,它将报告没有分配(并且也会更快)。
不幸的是,一些SubArray
当前(截至 2017 年末)对象必须存储在堆上。原因是因为 Julia 是 garbage-collected语言,这意味着如果 A
是一个不再使用的堆分配对象,则 A
可能会从内存中释放。关键点是:目前,引用 A
仅当其他变量存储在堆上时,才会计算这些变量的值。因此,如果全部 SubArray
s 存储在堆栈上,这样的代码会遇到问题:
function create()
A = rand(1000)
getfirst(view(A, 1:10))
end
function getfirst(v)
gc() # this triggers garbage collection
first(v)
end
因为create
不使用A
再次调用 getfirst
后,这不是“保护”A
。风险在于gc
调用最终可能会释放与 A
关联的内存(从而破坏 v
本身中条目的任何使用,因为 v
依赖于 A
),除非有 v
保护A
免遭垃圾收集。但目前,堆栈分配的变量无法保护堆分配的内存:垃圾收集器仅扫描堆上的变量。
您可以使用原始函数观看此操作,通过删除(与这些目的无关)T<:ZeroOne
修改为稍微减少限制。并允许任何 T
.
function check_alloc(x::AbstractArray{T}, temp::AbstractArray{T}) where T
s = 0
for i in 1 : 1000
myView = view(x, i : i + 9)
if myView == temp
s += 1
end
end
return s
end
a = collect(1:1010); # this uses heap-allocated memory
b = collect(1:10);
@time check_alloc(a, b); # ignore the first due to JIT-compilation
@time check_alloc(a, b)
a = 1:1010 # this doesn't require heap-allocated memory
@time check_alloc(a, b); # ignore due to JIT-compilation
@time check_alloc(a, b)
从第一个(使用 a = collect(1:1010)
)开始,您会得到
julia> @time check_alloc(a, b)
0.000022 seconds (1.00 k allocations: 47.031 KiB)
(请注意,每次迭代约为 47 字节,与 SubArray
包装器的大小一致),但从第二个(使用 a = 1:1010
)开始,您会得到
julia> @time check_alloc(a, b)
0.000020 seconds (4 allocations: 160 bytes)
这个问题有一个“明显”的解决方案:更改垃圾收集器,以便堆栈分配的变量可以保护堆分配的内存。这有一天会发生,但要正确支持这是一项极其复杂的操作。因此,目前的规则是任何包含堆分配内存引用的对象都必须存储在堆上。
最后还有一个微妙之处:Julia 的编译器非常智能,在某些情况下会忽略 SubArray
的创建。包装器(基本上,它以分别使用父数组对象和索引的方式重写代码,以便它永远不需要包装器本身)。为此,Julia 必须能够 inline任何函数都会调用创建 view
的函数。不幸的是,这里==
对于编译器来说稍微太大而不愿意内联它。如果您手动写出将要执行的操作,那么编译器将忽略 view
并且您还可以避免分配。
关于arrays - 使用数组 View 时出现意外的内存分配 (julia),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47590839/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许在 Stack Overflow 上提出有关通用计算硬件和软件的问题。您可以编辑问题,使其成为
当我尝试在 db2 中创建表时,它抛出以下错误 $ db2 CREATE TABLE employee(emp_id INT NOT NULL, emp_name VARCHAR(100)) sh:
我有: while (i < l) { if (one === two) { continue; } i++; } 但是 JSLint 说: Problem at line 1 chara
所以我有这个代码: char inputs[10] = ""; int numInputs = 0; while (numInputs < 10){ char c; printf("E
var ninja = { name: 'Ninja', say: function () { return 'I am a ' + this.name; }
我收到一个我不明白的错误,请注意,我是编码新手,所以这可能是一个简单的错误。 #include using namespace std; int main() { //Initialise Fahr
我正在使用 javascript 和 react,由于某种原因,我收到了一个奇怪的 token 错误。 这是发生错误的代码: renderNavBar() { if (!this.us
Closed. This question is off-topic。它当前不接受答案。
由于某种我无法解释的原因,编译器正在输出一个错误,指出它发现了一个意外的#else 标记。 这发生在文件的开头: #if defined( _USING_MFC ) #include "stda
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
这个问题在这里已经有了答案: Difference between sh and Bash (11 个答案) 关闭 2 年前。 我正在编写一个简单的 bash 脚本,我在 XX `(' unexpe
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 此问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-topic
我在 Windows 7 上编写了一个脚本,它不断给我一个错误“(此时出乎意料。”对于以下代码 if %vardns%=="NODNS" ( netsh interface ipv4 set ad
我正在尝试使用xmlstarlet(使用xpath)解析XML文件,但是出现语法错误,并且我不知道如何更正我的代码。 这是我的脚本: #!/bin/bash if [ $1=="author" ];
以下脚本旨在在目录中的所有文件上运行程序“senna”,并将每个文件的输出(保留输入文件名)写入另一个目录 for file in ./Data/in/*; do ./senna -iobta
我从 challengers.coffee 运行此代码,并收到错误 ActionView::Template::Error (SyntaxError: [stdin]:3:31:unexpected
我在 config.db.database; 行中有语法错误(意外的标记“.”)。这是我在文件中的代码 const config = require('../config/config') const
这一定很明显,但是我无法使它正常工作。我正在尝试传输应该用于构建$ classKey的对象,这反过来又导致删除所需的软件(amd64或i386)。好吧,这里的代码: $name = @("softwa
我正在使用 1.3.7 版学习 Grails,但我一直无缘无故地遇到以下语法错误: unexpected token: mapping @ line x, column y. 有一次,我通过运行“gr
我正在尝试找出这段Pascal代码的问题 function Factorial(n: integer): integer; begin if n = 0 then Result := 1
我是一名优秀的程序员,十分优秀!