【发布时间】:2017-06-09 17:30:21
【问题描述】:
我需要编写一个代码来使用只有一个规则的语法生成一个字符串。例如,如果规则是“G -> [G+G]”,我们将规则应用到“G”,结果是字符串“[G+G]”;如果我们将它应用到之前的结果,我们会得到“[[G+G]+[G+G]]”等等。换句话说,它是关于重写公理(规则的左侧)给定的次数, 遵循规则。
我收到了一段用 Octave 编写的代码,用于实现此操作(我不会包含代码,因为它有点长,但如果有必要理解或回答问题,我会包含)。我需要做的是在 Julia 中编写一个等效的函数;所以我写了这个
function generate_developedstring(axiom::ASCIIString, genome::ASCIIString, iterations::Int8)
tic()
developedstring = axiom
for i=1:iterations
developedstring = replace(developedstring, axiom, genome)
end
toc()
return developedstring
end
在我之前写的例子中,公理是“G”,基因组是“[G+G]”。
根据 julialang.org 发布的基准时间,Julia 应该比 Octave 快得多,但在这种情况下,Octave 是 Julia 的两倍 (我对两个代码都使用了相同的公理、基因组和迭代,并使用 tic toc 函数测量了时间)。
有什么方法可以让 Julia 代码更快?
编辑:首先,非常感谢你们的cmets。我会向你展示我得到的 Octave 代码(不是我写的):
function axiom = ls(genome)
tic
ProductionSystem = ['[=>[ ]=>] +=>+ -=>- G=>',genome];
rule = extract(ProductionSystem);
n_Rules = length(rule);
% starting string
axiom = 'G';
% iterations (choose only from 1 to 7, >= 8 critical,
% depends on the string and on the computer !!
n_Repeats = 3;
%CALCULATE THE STRING
%=================================
for i = 1:n_Repeats
% a single letter (axiom)
axiomINcells = cellstr(axiom);
for j = 1:n_Rules
% find all occurrences of that axiom
hit = strfind(axiom, rule(j).pre);
if (length(hit) >= 1)
for k = hit
% perform the rule
% (replace 'pre' by 'post')
axiomINcells{k} = rule(j).pos;
end
end
end
axiom = [];
for j = 1:length(axiomINcells)
% put all strings together
axiom = [axiom, axiomINcells{j}];
end
end
toc
function rule = extract(ProductionSystem)
% rules are separated by space character, and pre and post sides are
% separtated by '->'
% e.g. F->FF G->F[+G][-G]F[+G][-G]FG
i=0;
while (~isempty(ProductionSystem))
i=i+1;
[rule1,ProductionSystem] = strtok(ProductionSystem,' ');
[rule(i).pre,post] = strtok(rule1,'=>');
rule(i).pos = post(3:end);
if (~isempty(ProductionSystem)) ProductionSystem=ProductionSystem(2:end); % delete separator
end
end
关于我使用的 Julia 版本,它是 0.4.7。你还问我需要它跑多快;我只需要尽可能快地编写代码,而 Octave 更快的事实让我觉得我做错了什么。 再次感谢。
【问题讨论】:
-
一些建议首先:在函数内部使用
@time宏而不是tic/toc/,并进行两次基准测试,以排除编译时间。如果您在讨论论坛discourse.julialang.org 上发布一个最小的、可运行的示例,您可能会在此类性能问题上获得更多有用的帮助 -
Octave 代码是否都是一个矢量化调用?如果是,那么您就不是在比较 Octave 本身。相反,您会将 Julia 与可能在 C 中实现的优化良好的函数进行比较。您不应该期望 Julia 比 C 做得更好,尽管它通常应该很接近。
-
我在这上面花了一些时间,Julia 版本似乎很快——迭代字符串版本与直接递归打印单个字符串一样快,并且预分配适量的前面的空间。您能否发布 Octave 代码,以便我们查看它在做什么?
-
假设您的
replace函数每次都制作一个新副本,这可以替换为该函数的 mutating 版本,(名为replace!)而是现有的对象,避免内存分配。为此,developedstring可以有一些填充,以确保它不必在每次迭代时更改大小。 -
replace!不存在?因为Strings 是不可变的。