我正在从python生成自动C ++代码,特别是我需要为事件列表选择一些事件。我宣布了一些选择:
selectionA = Selection(name="selectionA", formula="A>10")
selectionB = Selection(name="selectionB", formula="cobject->f()>50")
selectionC = selectionA * selectionB # * means AND
这会生成C ++代码:
for(...) { // cicle on events
event = GetEvent(i);
bool selectionA = A>10;
bool selectionB = cobject->f()>50;
bool selectionC = (A>10) and (cobject->f()>50);
if (selectionA) { histo_selectionA->Fill(event); }
if (selectionB) { histo_selectionB->Fill(event); }
if (selectionC) { histo_selectionC->Fill(event); }
}
这不是很聪明,因为最聪明的代码将是:
bool selectionC = selectionA and selectionB
这个问题似乎很简单,但事实并非如此,因为我有100多个基本选择(如selectionA
或selectionB
)和300多个派生选择,当然派生选择可以是源自派生选择。明显的派生选择不是使用常规模式从基础选择中派生出来的。
我明白这很难回答,但有人可以给我一些提示吗?例如:是否真的有必要编写智能代码?我的意思是,编译器无法优化此代码?
答案 0 :(得分:2)
编译器不太可能优化此代码。部分原因是cobject->f()
可能有副作用,编译器无法看到。
您可以通过将您的bool声明为const
来轻微帮助。
否则,看起来您已经在重载运算符以构成选择。因此,使组合选择使用其组成的选择的名称而不是表达式应该不会太难。这会为您做一些优化,并允许编译器在可能的情况下进一步优化,特别是如果您将选择声明为const
。
您还必须小心发出代码,以按照在Python中创建选择对象的相同顺序初始化bool
标志。这将确保bool
始终在其稍后使用之前被声明和初始化。您可以通过在Python Selection
类中创建一个列表并使用__init__
方法将新Selection
添加到该列表中来实现此目的。当然,如果您创建了Selection
个对象,那么您可能会丢弃这些对象。但是,如果你把它们全部保留下来,那就有效了。
答案 1 :(得分:1)
编译器可能能够优化这个代码,但如果你有数百个复杂的表达式相互依赖,我会怀疑它会很好用。
但更基本的问题是:你真的需要优化吗?计算机速度很快,如果您不经常运行该代码,那么cobject->f()>50
运行一次或十次可能无关紧要。
另一方面,如果cobject->f()
有副作用(例如,它打印某些东西),编译器将永远不会优化掉重复的调用,你必须确保它只在你的调用中调用生成代码的次数与您希望打印的内容一样频繁。
最佳解决方案是,如果您的Selection
类在用作派生定义的一部分时可以输出name
而不是formula
。这有多难或多么取决于您的生成代码。
答案 2 :(得分:0)
作为对我评论的修正,我甚至认为你不需要像我建议的跟踪变量。为什么不尝试这个?
import string
class Selection:
selections = []
letters = string.letters[26:] + string.letters[:26]
def __init__(self, name, formula):
self.name = name
self.formula = formula
Selection.selections.append(self)
def __mul__(self, selection):
name = 'selection' + letters[len(selections)]
return Selection(name, self.name + ' and ' + selection.name)
@classmethod
def generate(c):
code = []
for selection in c.selections:
code.append('bool ')
code.append(selection.name)
code.append(' = ')
code.append(selection.formula)
code.append(';\n')
code.append('\n')
for selection in c.selections:
code.append('if (')
code.append(selection.name)
code.append(') { histo_')
code.append(selection.name)
code.append('->Fill(event); }\n')
return ''.join(code)
这当然有效,假设您只有52个选择对象,但该限制仅存在,因为此类仅生成表单选择的名称[A-Za-z]
答案 3 :(得分:0)
那么,如果我正确理解你的例子,你是在创建一组Selection对象,然后使用它们来生成代码?
首先,为什么不用C ++编写代码呢?实际上,你将Python中的C ++表达式作为字符串变量嵌入,并使用重载数学运算符来构造布尔表达式(事实上你觉得需要注释*表示并且表明这是一个不好的选择)?那简直太丑了!
话虽如此,你拥有所需的所有信息 - 在Python代码中,selectionA知道它的名字是“selectionA”而selectionB知道它的名字是“selectionB”。唯一的问题是,您没有提供足够的上下文来了解对象选择C的类型。我假设它与AndExpression类似,并且包含引用selectionA和selectionB(可能是param1和param2?)。只需输出"(" + self.param1.name + " && " + self.param2.name + ")"
。