그렇기 때문에 성능 프로파일 링에 대한 몇 가지 질문이 있지만 전체적인 그림을 찾지 못했습니다. 관련된 몇 가지 문제가 있으며 대부분 Q & A는 한 번에 몇 가지를 무시하거나 제안을 정당화하지 않습니다.C++에서 코드 속도를 테스트하는 가장 좋은 방법은 프로파일 러가 없거나 시도하는 것이 합리적이지 않습니까?
무엇이 궁금합니다. 똑같은 일을하는 두 가지 함수가 있고 속도의 차이에 대해 궁금한 점이 있다면, 타이머가있는 외부 도구없이 테스트하는 것이 맞습니까? 아니면 테스트에서 컴파일 된 결과가 결과에 많은 영향을 줍니까?
C + + 프로그래머로서 합리적이라면 외부 도구를 사용하는 것보다 훨씬 간단하므로 최선의 방법을 알고 싶습니다. 이해가된다면 모든 가능한 함정을 진행하십시오.
이 예제를 고려하십시오.
#include <algorithm>
#include <ctime>
#include <iostream>
typedef unsigned char byte;
inline
void
swapBytes(void* in, size_t n)
{
for(size_t lo=0, hi=n-1; hi>lo; ++lo, --hi)
in[lo] ^= in[hi]
, in[hi] ^= in[lo]
, in[lo] ^= in[hi] ;
}
int
main()
{
byte arr[9] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
const int iterations = 100000000;
clock_t begin = clock();
for(int i=iterations; i!=0; --i)
swapBytes(arr, 8);
clock_t middle = clock();
for(int i=iterations; i!=0; --i)
std::reverse(arr, arr+8);
clock_t end = clock();
double secSwap = (double) (middle-begin)/CLOCKS_PER_SEC;
double secReve = (double) (end-middle )/CLOCKS_PER_SEC;
std::cout << "swapBytes, for: " << iterations << " times takes: " << middle-begin
<< " clock ticks, which is: " << secSwap << "sec." << std::endl;
std::cout << "std::reverse, for: " << iterations << " times takes: " << end-middle
<< " clock ticks, which is: " << secReve << "sec." << std::endl;
std::cin.get();
return 0;
}
// Output:
// Release:
// swapBytes, for: 100000000 times takes: 3000 clock ticks, which is: 3sec.
// std::reverse, for: 100000000 times takes: 1437 clock ticks, which is: 1.437sec.
// Debug:
// swapBytes, for: 10000000 times takes: 1781 clock ticks, which is: 1.781sec.
// std::reverse, for: 10000000 times takes: 12781 clock ticks, which is: 12.781sec.
이슈 : 다음 코드는 같은 일을하고있는 2 가지 방법을 보여줍니다
사용하는 방법과 CPU 시간은 실제로 질문 아래의 코드에 의해 소비 얻을, 타이머- ?
- 컴파일러 최적화의 효과는 무엇입니까? (이 함수는 바이트를 앞뒤로 스왑하기 때문에 가장 효율적인 것은 아무 것도하지 않는 것입니다)?
- 여기에 제시된 결과를 고려해 볼 때 정확하다고 생각하십니까? (여러 번 실행하면 매우 비슷한 결과가 나옵니다.) 그렇다면 사용자 정의 함수의 단순성을 고려하여 std :: reverse가 너무 빨라지는 방식을 설명 할 수 있습니까? 나는이 테스트에서 사용한 vC++ 버전의 소스 코드가 없지만 GNU의 here is the implementation입니다. 그것은 나를 위해 완전히 이해할 수없는 함수 iter_swap으로 귀결됩니다. 이것은 또한 커스텀 함수보다 두 배 빠르다고 예상 할 수 있습니까? 만약 그렇다면 왜?
사색 :
이두 개의 고정밀 타이머가 제안되고있는 것 같다 clock() 및 QueryPerformanceCounter (Windows의 경우). 분명히 우리는 코드가 아닌 실시간으로 CPU 시간을 측정하고 싶지만, 이해할 수있는 한 이러한 기능은 기능을 제공하지 않으므로 시스템의 다른 프로세스가 측정을 방해합니다. This page gnu C 라이브러리에있는 모순 된 것처럼 보일지 만, 중단 점을 vC++에 넣을 때 디버깅 된 프로세스는 일시 중지 되었더라도 클럭 틱이 많이 발생합니다 (gnu에서 테스트하지 않았습니다). 이에 대한 대체 카운터가 누락 되었습니까? 아니면 최소한 특수한 라이브러리 또는 클래스가 필요합니까? 그렇지 않다면이 예제에서 클럭이 충분합니까? 아니면 QueryPerformanceCounter를 사용할 이유가 있습니까?
디버깅, 분해 및 프로파일 링 도구가 없으면 무엇을 알 수 있습니까? 실제로 일어나는 일이 있습니까? 함수 호출이 인라인 되었습니까? 디버거를 체크인 할 때 실제로 바이트가 바뀌지 만 테스팅보다는 왜 이론적으로 알 수 있습니다.
모든 방향에 감사드립니다.swapBytes 기능이 이제 빨리 표준 리버스 ::로 실행 tojas에서 hint에
갱신
감사합니다. 나는 바이트의 경우 임시 복사본이 단지 레지스터 여야한다는 것을 깨닫지 못했고 따라서 매우 빠르다. 우아함은 당신을 눈 멀게 할 수 있습니다. 공정 저점 Windows Management Instrumentation :
inline
void
swapBytes(byte* in, size_t n)
{
byte t;
for(int i=0; i<7-i; ++i)
{
t = in[i];
in[i] = in[7-i];
in[7-i] = t;
}
}
덕분에 ChrisW에서 tip에 난 창문에 당신이 (당신의 읽기)를 소비하는 실제 CPU 시간을 얻을 수있는 것으로 나타났습니다. 이것은 정밀도가 높은 카운터보다 확실히 더 흥미롭게 보입니다.
어떤 OS에 대해 궁금하십니까? 이전에 타이밍 코드를 썼을 때 다양한 OS에는 올바른 시계에 대해 다른 API 호출이있었습니다. –
WindowsXP에서 테스트 중이지만 다른 OS에 대한 정보는 – nus
입니다. Profiler를 처음 시도한 후에는 Profiler없이 시도할만한 가치가 있습니다. –