2010-08-29 31 views
2

我從python生成自動C++代碼,特別是我需要選擇一些事件列表的事件。我宣佈一些選擇:智能自動C代碼生成器嵌套如果在Python中

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多個基地選擇(如selectionAselectionB)和300多個衍生選擇,當然派生的選擇可以從派生的選擇ction。顯而易見的派生選擇不是使用常規模式從基本選擇派生的。

我明白,這是很難回答,但有人可以給我一些提示?例如:編寫智能代碼真的有必要嗎?我的意思是,編譯器無法優化此代碼?

+2

我相信大多數C++編譯器已經爲你做了這個。 – 2010-08-29 14:56:22

+0

爲什麼你在變量中只有第一代擴展到公式的標誌,然後纔是布爾條件的名稱? – blwy10 2010-08-29 15:06:24

+0

@ blwy10:因爲它不那麼容易,特別是你必須保證按照正確的順序聲明bool變量並且不需要重複。 – 2010-08-29 15:13:46

回答

2

編譯器不可能優化此代碼。部分原因是cobject->f()可能有編譯器無法看到的副作用。

你可以通過聲明你的bools爲const以小的方式提供幫助。

否則,它看起來像你已經超載運營商組成選擇。因此,使組合選擇使用其組成選擇的名稱而不是表達式不應太難。這會爲你做一些優化,如果可能的話,編譯器會進一步優化,特別是如果你聲明你的選擇布爾值爲const

您還必須小心地發出代碼,以按照在Python中創建選擇對象的相同順序初始化bool標誌。這將確保bool總是在稍後使用之前聲明和初始化。您可以通過在Python Selection類中添加一個列表來完成此操作,並使__init__方法將新的Selection添加到該列表中。當然,如果您創建Selection對象,然後丟棄這可能是一個問題。但是如果你把它們全部放在一起,它就會有效

1

編譯器可能能夠優化這個的代碼,但是如果你有數百個相互依賴的複雜表達式,我會懷疑它會工作得很好。

但是更基本的問題是:你真的需要優化嗎?計算機速度很快,如果您不經常運行該代碼,則運行一次或十次可能不會影響cobject->f()>50。另一方面,如果cobject->f()有副作用(例如,它打印了某些內容),編譯器將永遠不會優化重複調用,您將不得不確保僅在您生成的代碼中調用它作爲往往是你想要打印的東西。

如果您的Selection類在作爲派生定義的一部分使用時,只能輸出name而不是formula,那麼最好的解決方案是。這很難或容易取決於您的生成代碼。

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]

0

所以,如果我正確理解您的示例,您正在創建一組Selection對象,然後使用它們來生成代碼?

首先,爲什麼不直接用C++編寫代碼呢?實際上,您將C++表達式作爲字符串變量嵌入到Python中,並且使用重載數學運算符來構造布爾表達式(您認爲需要評論*表示AND意味着這是一個糟糕的選擇)?這簡直太難看了!這就是說,你有所有你需要的信息 - 在Python代碼中,selectionA知道它的名字是「selectionA」,而selectionB知道它的名字是「selectionB」。唯一的是,你沒有提供足夠的上下文來知道selectionC是什麼類型的對象。我假設它和AndExpression類似,並且保存了引用selectionA和selectionB(可能是param1和param2?)。只要它輸出"(" + self.param1.name + " && " + self.param2.name + ")"

+0

我使用python生成C++代碼,因爲代碼非常無聊,簡單,重複,但很長(10000+行)。 Python代碼生成C++代碼,編譯它,用parellel中的不同參數執行程序的一些程序,並使用它們的輸出。 – 2010-09-06 05:42:55

+0

在Python中,你不能重載和和或操作符,因爲它們很懶,所以你需要使用別的東西,它不是很難看 – 2010-09-06 05:43:38

+0

是的,但並不那麼簡單。關鍵是你需要知道你必須在'selectionC'之前聲明'selectionA'和'selectionB'。我的例子是微不足道的,現實生活不是。 – 2010-09-06 05:49:02