CPU 사용량이 높을수록 작업 속도가 느려지는 이유는 무엇입니까?

CPU 사용량이 높을수록 작업 속도가 느려지는 이유는 무엇입니까?

나는 사용하고있다속삭임.cpp일부 사운드 파일을 복사합니다. 이는 CPU 집약적인 프로세스이므로 최적의 설정을 찾으려고 노력하여 스레드 설정(-t)으로 몇 가지 테스트를 수행했지만 결과는 매우 혼란스러웠습니다. 내가 실행한 명령은 다음과 같습니다.

date; time ./main -t [number of threads] -m ggml-model.bin -f 5min-16kHz.wav; date

저는 6개 코어(+ 6개 하이퍼스레딩 코어)를 갖춘 Intel i7이 탑재된 Macbook Pro에서 이것을 실행하고 있습니다.

기본 설정(4개 스레드), 6개 및 12개 스레드(모든 CPU가 100%에서 실행되었음에도 불구하고 출력이 생성되지 않은 14개 스레드)를 시도했습니다. 결과는 다음과 같습니다.

스레드 시간 출력
4 1750.84초 사용자 11.02초 시스템 564% CPU 5:11.87 총
4 1862.04s 사용자 18.63s 시스템 553% CPU 5:39.58 총
6 2199.42초 사용자 16.79초 시스템 720% CPU 5:07.51 총
6 2212.72초 사용자 14.49초 시스템 722% CPU 5:08.22 총
12 4595.03초 사용자 22.21초 시스템 1053% CPU 7:18.47 총
12 4298.11s 사용자 22.53s 시스템 1059% CPU 6:47.85 총

보시다시피 스레드 수가 증가하면 CPU 부하도 증가합니다. CPU 로드가 증가함에 따라 실시간 시간이 비례적으로 감소할 것으로 예상할 수 있지만(1분 동안 100%는 대략 30분 동안 200%, 2분 동안 50%에 해당) 여기서는 그런 일이 발생하지 않습니다.

대신 4개 및 6개 스레드를 사용해도 거의 동일한 실시간 결과를 얻었으며, 6개 스레드를 실행할 때 CPU 사용량이 약 25% 증가했습니다. 12개의 스레드는 더욱 악화되어 6개의 스레드에 비해 CPU 시간은 두 배로 늘어나고 실시간은 40% 증가합니다.

나는 그것을 이해하지 못한다. 물론 더 많은 스레드가 선형적으로 확장되지는 않지만동일한 작업을 수행할 때 CPU 시간은 스레드 수에 관계없이 상당히 일정하게 유지되어야 합니다. 그렇죠? CPU 사용량이 증가하면 실시간이 감소해야 합니까?

작업과 하드웨어를 고려할 때 사용할 스레드 수에 대한 합리적인 설정은 무엇입니까?스레드가 I/O를 기다리는 경우를 대비해 코어 수 + 약간의 추가가 될 것으로 예상합니다. 제가 작업 중인 사운드 파일은 10MB이고, Whisper.cpp는 32GB 시스템에서 약 3,6GB를 사용합니다(현재 약 10GB는 사용되지 않으며 메모리 부족은 "녹색"입니다).


편집: 하나의 스레드만 사용하는 해당 값(-t 1):

1619.90초 사용자 20.86초 시스템 197% CPU 13:48.78 총

한 스레드가 CPU의 거의 200%를 사용하고 있음을 알 수 있습니다. 내가 이것을 이해하는지 잘 모르겠습니다. 하지만 실제 시간의 13분은 의미가 있습니다.

편집 2: CPU를 더 추가(-p)하면 성능이 저하됩니다.

-t 6 -p 3- 6804.14s user 38.58s system 1040% cpu 10:57.84 total(실제 시간의 2배, CPU 시간의 3~4배) -t 8 -p 2- 10573.58s user 57.47s system 1018% cpu 17:23.63 total(실제 시간의 3배 이상, CPU 시간의 6배) -t 4 -p 2- 2962.38s user 28.65s system 854% cpu 5:50.01 total(-t 4와 거의 동일)

내 생각에는 -p는 이 작업이 컴퓨터에 미치는 영향을 제한하려는 경우에만 사용해야 한다고 생각합니다. 그렇지 않으면 가능한 한 많은 프로세서를 사용하게 됩니다.

I/O는 아닌 것 같아요. 처음 5~10초 동안 3.08GB를 읽은 다음 나머지 실행(최소 5분 동안 지속) 동안 10MB 미만을 읽었습니다.

편집 3: -t 13즉, 내 CPU가 지원하는 것보다 하나 더 많은 스레드를 사용하면 매우 이상한 결과가 생성됩니다. 93213.70s user 450.23s system 978% cpu 2:39:36.88 total아니요, 농담이 아닙니다. CPU 시간은 50배 이상 높지만 -t 4CPU 사용률은 거의 두 배 높습니다(978% 대 564) %), 실시간 성능이 30배 이상 향상되었습니다.

CPU 시간이 20배 이상 증가한 것과 비교하면 -t 12CPU 사용량은 거의 동일하고 실시간도 20배 이상 증가합니다. 스레드를 하나 더 추가하면 됩니다.

여기에 뭔가 문제가 있는 것 아닌가요?

편집 4:

선택된 벤치마크 데이터

./bench -m ./models/ggml-small.en.bin -t 4

system_info: n_threads = 4 / 12 | AVX = 1 | AVX2 = 1 | AVX512 = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 1 | SSE3 = 1 | VSX = 0 | 

whisper_print_timings:     load time =   540.82 ms
whisper_print_timings:   encode time =  3490.52 ms
whisper_print_timings:    total time =  4031.40 ms

5개 스레드는 4개 스레드보다 약 8% 빠릅니다.

whisper_print_timings:     load time =   547.27 ms
whisper_print_timings:   encode time =  3193.27 ms
whisper_print_timings:    total time =  3740.58 ms

6개 스레드는 5개 스레드보다 1% 느립니다.

whisper_print_timings:     load time =   591.16 ms
whisper_print_timings:   encode time =  3158.88 ms
whisper_print_timings:    total time =  3750.10 ms

7개 스레드는 6개 스레드보다 15% 느립니다. 거기에서 모든 것이 내리막 길이었습니다. 내 생각에 이 작업은 하이퍼스레드 코어가 아닌 내가 가지고 있는 6개의 "실제" 코어만 사용하는 것 같습니다. 이론적으로는 6개의 스레드가 5개의 스레드보다 더 빨라야 한다고 생각하지만, 이 벤치마크를 실행하는 동안 컴퓨터가 스레드 중 하나를 중단하고 때때로 코어를 사용하는 다른 작업을 수행한다고 상상합니다.

편집 5:

-20이라는 좋은 값으로 벤치마크를 실행하면 몇 가지 흥미로운 결과가 나왔습니다(여기에는 총 시간만 나열되어 있습니다).

Threads    Total time (ms)    ∆ (negative is better)
      4               3512    -13%
      5               3510     -6%
      6               3251 !! -13%
      7               3962     -8%

Δ는 일반 우선순위를 갖는 동일한 수의 스레드와 비교됩니다. 우선순위가 높은 6개의 스레드는 보통 우선순위의 기본 설정보다 19% 빠릅니다.

답변1

어느 시점에서 스레드 수를 늘리면 계산 메모리가 제한되어 성능이 향상되지 않습니다. whisper.cpp스레드를 동기화하기 위해 바쁜 루프를 사용하기 때문에 CPU 사용량이 계속 증가합니다 . 이는 더 많은 CPU 리소스를 사용하고 많은 CPU 주기를 낭비하지만 컨텍스트 전환 및 뮤텍스/조건 변수의 기타 부작용을 방지하여 대기 시간을 줄이는 데 도움이 됩니다.

--processors매개변수는 CPU 프로세서를 나타내지 않습니다. 이는 whisper.cpp오디오를 병렬로 처리하는 독립 프로세서입니다. 이 기능에 대한 자세한 내용은 여기에서 확인할 수 있습니다.

https://github.com/ggerganov/whisper.cpp/pull/110

답변2

스레드 설정(-t)으로 몇 가지 테스트를 수행했습니다.

이것은 실제로 매우 좋은 생각입니다... -p 옵션에 대해 뭔가를 지정하는 한:

-p N, --processors N [1 ] 계산 중에 사용할 프로세서 수

그렇지 않으면 사용되는 프로세서 수가 기본적으로 1로 설정됩니다. 실제 이익 없이 컨텍스트 전환에 많은 시간을 낭비하게 됩니다. (유일한 이점은 IO가 다른 실행 가능한 스레드의 이점을 얻기를 기다리는 한 스레드의 시간을 활용하는 것일 수 있지만 애플리케이션이 CPU에 과도하게 바인딩되어 있음을 인정하는 것입니다...)

실제로 어떤 종류의 CPU 집약적 애플리케이션이라도 단일 프로세서에서 작업하는 스레드가 많을수록 낭비도 커집니다. 방금... ​​증명했습니다. ;-)

따라서 나는 다음을 권장합니다.

  • 1/기본 성능 결정, 기본값 t=4;
  • 2/ t=4 및 p=2이고 이점이 중요하지 않을 때까지 t를 늘립니다.
  • 3/ 실행 중인 다른 애플리케이션이 손상되기 시작할 때까지 더 높은 p-값으로 2를 반복합니다.

개발자는 애플리케이션의 성능을 저하시키는 현명하지 못한 기본값을 제공하지 않을 것이라고 확신합니다.
여기에 적용된 것처럼 개발자는 애플리케이션이 상당히 IO에 묶여 있다는 점을 인정하는 것 같으므로 4:1의 t/p 비율을 권장합니다.


다음 작업 업데이트

부인 성명:Intel의 Turbo Boost 기술, 특히 Core i7이 내부적으로 어떻게 코어 주파수/오프라인 코어를 수정하고 멀티스레드 애플리케이션 성능에 미치는 영향을 결정하는지 이해할 수 없습니다.

편집 5:이 데이터 집합은 논리적 숫자를 제공합니다.
CPU 바인딩 스레드를 낮추는 데 적합한 값은 예약하는 동안 CPU가 예약되도록 허용되는 시간을 늘려 훨씬 저렴한 컨텍스트 스위치 비용으로 작업 부하를 처리합니다.
이 데이터 세트는 또한 6개의 코어만 사용되었음을 보여줍니다. 이유는 무엇입니까? 터보? HT가 비활성화되었나요? 이 중 정확히 무엇인지 알 수 있는 방법이 있다면...

관련 정보