2013-11-25 8 views
0

람다 함수에 속도 문제가 있습니다.람다의 속도 대 함수의 인라이닝

void for_each_lit(
    const OccurClause& cl 
    , std::function<void (const Lit lit)> func 
); 

기능 번 lit_diff_watches 실행 수백만, 그것은 예에 3.3s를 취

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 함수의 서명은 다음과 같습니다 여기에 코드입니다. 그러나 스위치의 주석 처리를 제거하고 for_each_line (스위치의 복사 붙여 넣기)을 주석 처리하면 똑같은 실행을 위해 1.7 초를 얻게됩니다. 시간의 99 % 인 watch_binary_t 또는 watch_tertiary_t이 발생합니다. 즉, lit_diff_watches 함수 호출 당 매우 적은 수의 명령어 만 실행되어야합니다.

내가 뭘 잘못하고 있는지 말해 줄 수 있습니까? 동작은 GCC 4.7과 현재 llvm-svn (2013 년 11 월 25 일)에서 동일합니다. 타이밍 차이는 미미합니다. 함수 호출이 인라인되지는 않았지만 저는 전문가가 아닙니다. 왜냐하면이 switch(..){..}이 코드의 많은 부분에 있고 람다 코드 & for_each_lit을 사용하면 코드를 상당히 정리할 수 있기 때문에 이것을 수정하고 싶습니다. 그러나, 나는 이걸로 너무 많은 속도를 풀 수 없습니다. 10-20 %는 좋지만 거의 2 배의 속도 저하는 너무 많습니다.

+3

최고 최적화 수준을 사용해야합니다. 그것 이외에, 우리는 아마 당신이 완전한 예제없이 도움을 줄 수 없습니다. – zch

+7

'std :: function'으로 변환하지 마십시오. 대신 템플리트를 사용하십시오. –

답변

1

cbreak-work는 #C++ freenode IRC 채널에서 도움이되었습니다. 그는 "Kerrek SB"가 의견에서 쓴 것을 제안했다. 나는에 for_each_lit의 선언을 변경 :

template<class Function> 
void for_each_lit(
    const OccurClause& cl 
    , Function func 
); 

과 속도는 이제 모두 구현에 대해 동일합니다. 분명히 컴파일러는 가상 함수 호출을 방해하기 위해 링크 타임 최적화를 수행 할 수 없었기 때문에 오버 헤드가 엄청났습니다.

모두에게 도움을 주셔서 감사합니다.