У меня проблемы со скоростью с лямбда-функциями. Вот код:
Lit Simplifier::lit_diff_watches(const OccurClause& a, const OccurClause& b)
{
set_seen_for_lits(b, 1);
size_t num = 0;
Lit toret = lit_Undef;
const auto check_seen = [&] (const Lit lit) {
if (seen[lit.toInt()] == 0) {
toret = lit;
num++;
}
};
for_each_lit(a, check_seen);
/*switch(a.ws.getType()) {
case CMSat::watch_binary_t:
check_seen(a.lit);
check_seen(a.ws.lit2());
break;
case CMSat::watch_tertiary_t:
check_seen(a.lit);
check_seen(a.ws.lit2());
check_seen(a.ws.lit3());
break;
case CMSat::watch_clause_t: {
const Clause& clause = *solver->clAllocator->getPointer(a.ws.getOffset());
for(const Lit lit: clause) {
check_seen(lit);
}
break;
}
}*/
set_seen_for_lits(b, 0);
if (num == 1)
return toret;
else
return lit_Undef;
}
for_each_lit
подпись функции:
void for_each_lit(
const OccurClause& cl
, std::function<void (const Lit lit)> func
);
Функция lit_diff_watches
работает миллионы раз, и это займет 3,3 с на примере. Однако, когда я раскомментирую переключатель и закомментирую for_each_line
(это копия-вставка переключателя), я получаю 1.7s для того же точного запуска. Обратите внимание, что в 99% случаев watch_binary_t
или же watch_tertiary_t
случается, то есть только очень немногие инструкции должны быть выполнены за lit_diff_watches
вызов функции.
Подскажите, пожалуйста, что я делаю не так? Поведение одинаково как для GCC 4.7, так и для текущей версии llvm-svn (25 ноября 2013 г.), временные различия незначительны. Я предполагаю, что вызов функции не встроен, но я не эксперт. Я хотел бы исправить это, потому что это switch(..){..}
находится во многих-многих местах в коде, и использование лямбд & for_each_lit
значительно очистит код Однако я не могу потерять так много скорости из-за этого. 10-20% было бы хорошо, но замедление почти в 2 раза — это слишком много.
cbreak-работа помогла мне на IRC-канале # c ++ freenode. Он предложил то, что «Керрек С.Б.» написал выше в комментариях. Я изменился for_each_lit
объявление к:
template<class Function>
void for_each_lit(
const OccurClause& cl
, Function func
);
и скорость теперь одинакова для обеих реализаций. По-видимому, компилятор не смог выполнить оптимизацию во время компоновки, чтобы убрать вызов виртуальной функции, поэтому накладные расходы были огромными.
Спасибо всем за помощь всем!
Других решений пока нет …