programing tip

마이크로 벤치마킹이란 무엇입니까?

itbloger 2020. 12. 31. 08:02
반응형

마이크로 벤치마킹이란 무엇입니까?


이 용어가 사용되었다고 들었지만 그 의미가 무엇인지 잘 모르겠습니다.

  • 그것은 무엇을 의미하고 무엇을 의미하지 않습니까?
  • IS 및 IS N'T 마이크로 벤치마킹의 예는 무엇입니까?
  • 마이크로 벤치마킹의 위험은 무엇이며 어떻게 피합니까?
    • (또는 좋은 일입니까?)

깡통에 적힌 내용을 정확히 의미합니다. 운영 체제의 커널에 대한 시스템 호출과 같은 "작은"것의 성능을 측정하는 것입니다.

위험은 사람들이 마이크로 벤치마킹에서 얻은 결과를 사용하여 최적화를 지시 할 수 있다는 것입니다. 그리고 우리 모두 알다시피 :

97 % 정도의 작은 효율성은 잊어야합니다. 조기 최적화는 모든 악의 근원입니다. "-Donald Knuth

마이크로 벤치 마크의 결과를 왜곡하는 많은 요인이있을 수 있습니다. 컴파일러 최적화도 그중 하나입니다. 측정되는 작업에 시간이 거의 걸리지 않아 측정에 사용하는 것이 실제 작업 자체보다 오래 걸리면 마이크로 벤치 마크도 왜곡됩니다.

예를 들어 누군가 for루프 의 오버 헤드에 대한 마이크로 벤치 마크를 취할 수 있습니다 .

void TestForLoop()
{
    time start = GetTime();

    for(int i = 0; i < 1000000000; ++i)
    {
    }

    time elapsed = GetTime() - start;
    time elapsedPerIteration = elapsed / 1000000000;
    printf("Time elapsed for each iteration: %d\n", elapsedPerIteration);
}

분명히 컴파일러는 루프가 전혀 아무것도하지 않고 루프에 대한 코드를 생성하지 않는다는 것을 알 수 있습니다. 따라서 elapsed의 값 elapsedPerIteration은 거의 쓸모가 없습니다.

루프가 뭔가를하더라도 :

void TestForLoop()
{
    int sum = 0;
    time start = GetTime();

    for(int i = 0; i < 1000000000; ++i)
    {
        ++sum;
    }

    time elapsed = GetTime() - start;
    time elapsedPerIteration = elapsed / 1000000000;
    printf("Time elapsed for each iteration: %d\n", elapsedPerIteration);
}

컴파일러는 변수 sum가 어떤 용도로도 사용되지 않음을 확인하고이를 최적화하고 for 루프도 최적화합니다. 하지만 기다려! 이렇게하면 어떨까요?

void TestForLoop()
{
    int sum = 0;
    time start = GetTime();

    for(int i = 0; i < 1000000000; ++i)
    {
        ++sum;
    }

    time elapsed = GetTime() - start;
    time elapsedPerIteration = elapsed / 1000000000;
    printf("Time elapsed for each iteration: %d\n", elapsedPerIteration);
    printf("Sum: %d\n", sum); // Added
}

컴파일러 sum는 항상 상수 값 이라는 것을 인식하고 모든 것을 최적화 할 수있을만큼 똑똑 할 수 있습니다 . 오늘날 많은 사람들이 컴파일러의 최적화 기능에 놀랄 것입니다.

하지만 컴파일러가 최적화 할 수없는 것은 어떨까요?

void TestFileOpenPerformance()
{
    FILE* file = NULL;
    time start = GetTime();

    for(int i = 0; i < 1000000000; ++i)
    {
        file = fopen("testfile.dat");
        fclose(file);
    }

    time elapsed = GetTime() - start;
    time elapsedPerIteration = elapsed / 1000000000;
    printf("Time elapsed for each file open: %d\n", elapsedPerIteration);
}

이것조차도 유용한 테스트가 아닙니다! 운영 체제는 파일이 매우 자주 열리는 것을 인식 할 수 있으므로 성능 향상을 위해 파일을 메모리에 미리로드 할 수 있습니다. 거의 모든 운영 체제에서이 작업을 수행합니다. 응용 프로그램을 열 때도 같은 일이 발생합니다. 운영 체제는 가장 많이 연 상위 ~ 5 개의 응용 프로그램을 파악하고 컴퓨터를 부팅 할 때 메모리에 응용 프로그램 코드를 미리로드 할 수 있습니다.

실제로, 참조 지역성 (예 : 배열 대 연결 목록), 캐시 및 메모리 대역폭의 영향, 컴파일러 인라인, 컴파일러 구현, 컴파일러 스위치, 프로세서 코어 수, 프로세서 수준에서의 최적화 등 수많은 변수가 작용합니다. , 운영 체제 스케줄러, 운영 체제 백그라운드 프로세스 등

따라서 마이크로 벤치마킹은 많은 경우에 정확히 유용한 측정 항목이 아닙니다. 전체 프로그램 벤치 마크를 잘 정의 된 테스트 케이스 (프로파일 링)로 대체하지는 않습니다. 먼저 읽을 수있는 코드를 작성한 다음 프로파일 링하여 수행해야하는 작업이 있는지 확인합니다.

마이크로 벤치 마크는 그 자체로 악한 것은 아니지만 신중하게 사용해야 한다는 점을 강조하고 싶습니다 (컴퓨터와 관련된 다른 많은 것들에 대해서도 마찬가지입니다).


마이크로 벤치마킹에 대한 정의는 없지만이를 사용한다는 것은 특정 하드웨어 1 또는 언어 기능 의 성능을 테스트하도록 설계된 작은 인공 벤치 마크를 의미 합니다. 대조적으로 더 나은 벤치 마크는 실제 작업을 수행하도록 설계된 실제 프로그램입니다. (두 사건 사이에 딱딱한 선을 그리는 것은 무의미합니다, IMO, 시도하지 않을 것입니다.)

마이크로 벤치마킹의 위험은 완전히 오해의 소지가있는 결과를 제공하는 벤치 마크를 작성하기 쉽다는 것입니다. Java 마이크로 벤치 마크의 몇 가지 일반적인 트랩은 다음과 같습니다.

  • 컴파일러가 추론 할 수있는 코드를 작성하는 것은 유용한 작업이 아니므로 완전히 최적화합니다.
  • Java 메모리 관리의 "울퉁불퉁 한"특성을 고려하지 않고
  • JVM 시작 효과를 고려하지 않습니다. 예를 들어, 클래스를로드하고 JIT를 컴파일하는 데 걸리는 시간, 그리고 (반대로) 메소드가 JIT 컴파일되면 발생하는 실행 속도 향상.

그러나 위의 문제를 해결 한 후에도 해결할 수없는 벤치마킹에 대한 체계적인 문제가 있습니다. 벤치 마크의 코드와 동작은 일반적으로 당신이 정말로 관심을 갖는 것과 거의 관련이 없습니다. , 응용 프로그램이 수행되는 방식. 프로그램은 말할 것도없고 벤치 마크에서 일반 프로그램으로 일반화 할 수있는 "숨겨진 변수"가 너무 많습니다.

For these reasons, we regularly advise people NOT to waste their time with micro-benchmarks. Instead, it is best to write simple and natural code, and use a profiler to identify areas that need to be hand optimized. Interestingly, it usually turns out that the most significant performance problems in real applications are due to bad design of data structures and algorithms (including networking, database and threading-related bottlenecks) rather than the kind of things that typical micro-benchmarks are trying to test.

@BalusC has provided an excellent link to material on this topic in the Hotspot FAQ page. And here is a link to an IBM whitepaper by Brian Goetz.


1 - Experts would not even try to do hardware benchmarking in Java. There are too many "complex things" happening between the bytecodes and the hardware to draw valid / useful conclusions about hardware from the raw results. You would be better off using a language that is closer to the hardware; e.g. C or even assembly code.


  • What DOES it mean and what DOESN'T it mean?

I would say micro-benchmarking simply means measuring something tiny. Tiny is probably context dependent, but typically on the level of a single system call or something similar. Benchmarking refers to everything above.

  • What are some examples of what IS and ISN'T microbenchmarking?

This article lists measuring time of a getpid() system call and measuring the time to copy memory using memcpy() as examples of micro-benchmarking.

Any measurement of an algorithm implementation etc would not count as micro-benchmarking. Especially result reports listing tasks with decreasing execution time probably seldom count as micro benchmarking.

  • What are the dangers of microbenchmarking and how do you avoid it?

The obvious danger is that it tempts developers to optimize the wrong parts of a program. Another danger is that it is notoriously difficult to do measurements of something small accurately. The easiest way to avoid it is probably just to get a good picture of where the most time is spent in the program.

People usually say "don't do micro-benchmarking" but what they probably mean is "don't make optimization decisions based on micro-benchmarks".

  • (or is it a good thing?)

It's not at all a bad thing per se as others here, and many webpages seem to suggest. It has it's places. I work with program rewriting and runtime aspect weaving etc. We usually publish micro-benchmarks of our added instructions, not to guide any optimizations, but making sure that our extra code has close to no impact on the execution of the rewritten program.

It's an art however, especially in the context of a VM that has JIT, warm-up times etc. A well described approach for Java is descrbed here.


in the book(Java Performance The Definitive Guide) it has this definition and example aboout microbenchmarks

  1. Microbenchmarks

    A microbenchmark is a test designed to measure a very small unit performance: the time to call a synchronized method versus a nonsynronized method; the overhead in creating a thread versus asing a thread pool; te time to execute one arithmetic algoritm versus an alternate implementation; and so on.

    Microbenchmarks may seem like a good idea, but they are very difficult to write correctly. consedider the following code, which is an attempt to write a mocrobenchmark that test the permorfance od defferent implementation of a method to compute the 50th Fibonaccio number:

public void doTest(){
double l;
long then = System.currentTimeMillis();

for(int i = 0; i < nLoops; i++){
 l = fibImpl1(50);
}

long now = system.currentTimeMillis();
System.out.println("Elapsed time: " + (now - then))

}

...

private double fibImpl1(int n){
if(n < 0) throw new IllegalArgumentException("Must be > 0");
if(n == 0) return 0d;
if(n == 1) return 1d;
double d = fibImpl1(n - 2) + fibImpl(n - 1);
if(Double.isInfinited(d)) throw new ArithmeticException("Overflow");
return d;
}

Microbenchmarks must use their results.

The biggest problem with this code is that it never actually changes any program state. Because the result of the Fibonacci calculation is never used, the compiler is free to discard that calculation, A smart compiler (Including current java 7 and 8 compilers)

will end up executing this code:

long then = System.currentTimeMillis();
long now = System.currentTimeMillis();
System.out.println("Elapsed time: " + (now - then));

AS result, the elapsed time will be only a few millisecond, regardless of the implementation of the fibonaci method, or the number of times the loop is supposed to be executed.

There is a way around that particular issue: ensure that each result is read, nor simply weitten. In practice, changing the definition of l from a local variable to an instance variable (declared with the volatile keyword) will allow the performance of the method to be measured.


Here are some good articles by Brian Goetz that explain why (micro)benchmarking is especially hard in Java:


Microbenchmarking is benchmarking I don't think is worthwhile. Effective benchmarking is benchmarking I think is worth the time.

Generally speaking, microbenchmarking is (as in silico says) attempting to measure the performance of some very granular task, which is both hard to do well and usually pointless in the context of actual performance headaches.

ReferenceURL : https://stackoverflow.com/questions/2842695/what-is-microbenchmarking

반응형