(Julia 1.x)通过初始化变量增加分配?
我正在编写的程序有一个用户编写的文件,其中包含要在代码中读取和实现的参数。用户应该能够通过使用注释字符(我使用了“#”,与Julia的约定)对输入文件进行分隔来对其进行注释-在解析输入文件时,代码将删除这些注释。在对这个解析器进行小优化的同时,我注意到在调用(Julia 1.x)通过初始化变量增加分配?,julia,Julia,我正在编写的程序有一个用户编写的文件,其中包含要在代码中读取和实现的参数。用户应该能够通过使用注释字符(我使用了“#”,与Julia的约定)对输入文件进行分隔来对其进行注释-在解析输入文件时,代码将删除这些注释。在对这个解析器进行小优化的同时,我注意到在调用split()之前实例化第二个变量会对数字分配产生明显的影响: function removecomments1(line::String; dlm::String="#") str::String = "" try
split()
之前实例化第二个变量会对数字分配产生明显的影响:
function removecomments1(line::String; dlm::String="#")
str::String = ""
try
str, tmp = split(line, dlm)
catch
str = line
finally
return str
end
end
function removecomments2(line::String; dlm::String="#")
str::String = ""
tmp::SubString{String} = ""
try
str, tmp = split(line, dlm)
catch
str = line
finally
return str
end
end
line = "Hello world # my comment"
@time removecomments1(line)
@time removecomments2(line)
$> 0.016092 seconds (27.31 k allocations: 1.367 MiB)
0.016164 seconds (31.26 k allocations: 1.548 MiB)
我的直觉(来自C++背景)告诉我,初始化两个变量应该导致速度的增加,并最小化进一步分配,因为编译器已经被告知需要第二个变量以及它的对应类型,但是这似乎不成立。为什么会这样
旁白:有没有更有效的方法来实现与这些功能相同的结果 编辑: 在Oscar Smith的一篇文章之后,将str
初始化为typeSubString{String}
而不是String
使分配减少了约10%:
$> 0.014811 seconds (24.29 k allocations: 1.246 MiB)
0.015045 seconds (28.25 k allocations: 1.433 MiB)
来解释这是怎么做的,想想分裂函数会在C++中被写什么。它不会复制,而是返回一个
char*
。因此,str::String=”“
所做的就是让Julia创建一个要忽略的额外字符串对象。在您的示例中,需要try-catch块的唯一原因是,您正在尝试对split
的输出进行解构,即使在输入行没有注释时split
将返回一个单元素数组。如果您只需从split
的输出中提取第一个元素,则可以避免try-catch构造,这将节省您的时间和内存:
julia> using BenchmarkTools
julia> removecomments3(line::String; dlm::String = "#") = first(split(line, dlm))
removecomments3 (generic function with 1 method)
julia> @btime removecomments1($line);
198.522 ns (5 allocations: 224 bytes)
julia> @btime removecomments2($line);
208.507 ns (6 allocations: 256 bytes)
julia> @btime removecomments3($line);
147.001 ns (4 allocations: 192 bytes)
在对原始问题的部分回答中,预分配主要用于数组,而不是字符串或其他标量。有关何时使用预分配的更多讨论,请查看。这两个函数中都存在此初始化,因此它肯定不会对分配产生影响吗?无论哪种方式,如果两个函数都没有使用
str::String=”“
,那么我可能应该更改代码的这一部分,但是完全删除初始化会抛出LoadError:UndefVarError:str not defined
。相反,使用类型子字符串{String}
初始化它会减少分配,但这对需求来说还是多余的吗?在得出任何结论之前,您应该使用BenchmarkTools并确保您不是在全局范围内进行基准测试<代码>使用基准工具@b时间removecomments1($line)@btime removecomments2($line)。我不知道在全局范围内进行基准测试会有什么不同,但下面是使用@btime
而不是@time
的结果:249.887 ns(5个分配:224字节)
262.174ns(6个分配:256字节)
此外,您的@time
调用似乎捕获了两个函数的编译时间。在使用@time
之前,应至少运行一次函数removecomments1(line)==removecomments2(line)
在使用@time
之前最好先运行一行。预分配主要用于数组,而不是字符串或其他标量。据我所知,预分配字符串并没有性能或内存优势。天哪,这是一个显著的改进,尤其是当catch
通常生效时!我以前没有遇到过first()
,搜索引擎只显示它正在使用和更新。即使搜索也不会显示任何内容—它是什么,它做什么?first
是一个通用函数,用于提取集合的第一个元素。它在各种包中都有扩展其功能的方法。