умный автоматический генератор кода C с вложенным if в python - PullRequest
2 голосов
/ 29 августа 2010

Я генерирую автоматический код 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+ базовых выборов (как selectionA или selectionB) и 300+ производных выборов, и, конечно, производный выбор может быть получен из производного выбора , Очевидные производные выборки не выводятся из базовых выборок с использованием регулярного шаблона.

Я понимаю, что ответить сложно, но может кто-нибудь дать мне несколько советов? Например: действительно ли необходимо писать умный код? Я имею в виду, компиляторы не могут оптимизировать этот код?

Ответы [ 4 ]

2 голосов
/ 29 августа 2010

Маловероятно, что компилятор сможет оптимизировать этот код. Отчасти потому, что cobject->f() может иметь побочные эффекты, которые компилятор не видит.

Вы можете помочь незначительным образом, объявив ваши bools как const.

В противном случае, похоже, что вы уже перегружаете операторы для составления выборок. Поэтому не должно быть слишком сложно заставить составной выбор использовать имена выборок, из которых он состоит, вместо выражений. Это делает некоторую оптимизацию для вас и позволит компилятору оптимизировать, если возможно, дальнейшую оптимизацию, особенно если вы объявите свой выбор bools как const.

Вы также должны быть осторожны, чтобы выдать код для инициализации флагов bool в том же порядке, в котором объекты выбора создаются в Python. Это гарантирует, что bool всегда объявляется и инициализируется до того, как будет использовано позже. Вы можете сделать это, имея список в классе Python Selection, а метод __init__ добавляет новый Selection в этот список. Конечно, если вы создаете Selection объекты, которые затем выбрасываете, это может быть проблемой. Но если вы сохраните их все, это сработает.

1 голос
/ 29 августа 2010

Компиляторы могут оптимизировать этот код, но если у вас есть сотни сложных выражений, которые зависят друг от друга, я сомневаюсь, что он будет работать так же хорошо.

Но болееОсновной вопрос: вам действительно нужна оптимизация?Компьютеры работают быстро, и если вы не запускаете этот код очень часто, то может не иметь значения, запускается ли cobject->f()>50 один или десять раз.

С другой стороны, если cobject->f() имеет побочные эффекты(как, например, он что-то печатает), компилятор никогда не оптимизирует повторяющиеся вызовы, и вам нужно будет убедиться, что он вызывается в вашем сгенерированном коде так часто, как вы хотите, чтобы он что-то печатал.* Лучшим решением было бы, если бы ваш класс Selection мог просто вывести name вместо formula, когда он используется как часть производного определения.Насколько это сложно или просто, зависит от вашего генерирующего кода.

0 голосов
/ 06 сентября 2010

Итак, если я правильно понимаю ваш пример, вы создаете набор объектов Selection и затем используете их для генерации кода?

Прежде всего, почему бы просто не написать код на C ++? На самом деле, вы встраиваете выражения C ++ в Python как строковые переменные и используете перегруженные математические операторы для создания логических выражений (тот факт, что вам необходимо прокомментировать, что * означает, что AND означает, что это плохой выбор)? Это просто безобразно!

При этом у вас есть вся необходимая информация - в коде Python selectionA знает, что его имя - "selectionA", а selectionB знает, что его имя - "selectionB". Единственное, вы не предоставляете достаточно контекста, чтобы знать, какой тип объекта selectionC. Я предполагаю, что это что-то вроде AndExpression, и содержит ссылки selectionA и selectionB (может быть, как param1 и param2?). Просто выведите "(" + self.param1.name + " && " + self.param2.name + ")".

0 голосов
/ 29 августа 2010

Как поправка к моему комментарию, я даже не думаю, что вам понадобится переменная отслеживания, как я и предлагал.Почему бы не попробовать это?

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]

...