벤치 마크는 일반적으로 쓸모가 없습니다. dhrystone은 가장 오래된 것들 중 하나이며 파이프 라인과 너무 많은 컴파일러 최적화 이전에는 약간의 가치가있을 수 있습니다. 나는 15 년 전에 dhrystone을 사용하기 시작한 때를 대략 포기했다고 생각합니다.
당신이 어떻게 현대 프로세서의 작업을 이해한다면 주로 두 가지 지침입니다이 코드
.globl ASMDELAY
ASMDELAY:
sub r0,r0,#1
bne ASMDELAY
bx lr
는, 동일한 칩에 실행 시간을 크게 다를 수 있음을 입증하는 간단하다. 이것을 보는 간단한 방법은 캐시와 프리 페처 등을 끄고이 코드를 0x0000 오프셋에 놓고 값을 지정하여 호출하십시오. 0x0004 repeat에 놓고 0x0008에서 반복하십시오. 계속해라. 빼기와 브랜치 사이에 1, 2 등의 nop을 넣을 수 있습니다. 다양한 오프셋에서 시도해보십시오.
THEN, 각 정렬에 대해 캐시를 켜고 플래시에 대해 프로세서 외부에 프리 페치가 있으면 켜고 끕니다.
그 다음에는 클럭 속도에 따라 대기 상태를 조정해야하는 MCU에 대해 시계를 변경하십시오.
단일 MCU에서는 본질적으로 두 개의 명령어가 매우 많이 실행 시간이 다릅니다. 어떤 경우에는 다른 것보다 20 배 더 길게 말할 수 있습니다.
이제 작은 프로그램이나 dhrystone 프로그램의 작은 부분을 차지하십시오. 귀하의 MCU에 대해 컴파일하십시오. 얼마나 많은 지침이 표시됩니까? 주요 최적화 및 컴파일 명령 줄의 다른 변형, 코드가 얼마만큼 변경되는지 확인하십시오. 두 개의 명령어가 실행 시간에 20 번 호출 할 수 있다면 어떻게 달라질 수 있습니까? 200 개의 명령어 나 2000 개의 명령어는 얼마나 나쁠까요? 그것은 꽤 나빠질 수 있습니다.
지금 가지고있는 컴파일러 옵션으로 지금 가지고있는 dhrystone 프로그램을 가지고 있다면, 부트 스트랩으로 가서, 한개의 nop (플래시에서 하나의 명령으로 전체 바이너리를 이동시키는 것)을 다시 실행하십시오. 2, 3, 4를 더하십시오. 한 시스템에서 벤치 마크를 실행중인 다른 mcus를 비교하지 않고 있습니다.
각 캐시가있는 경우 i 캐시가 있거나없는 캐시에서 실행하거나 캐시하지 않고 실행하십시오. 플래시 프리 페치를 켜고 끄십시오. 쓰기 버퍼가있는 경우 켜고 끌 수 있습니다. 여전히 동일한 컴파일러에 남아있는 동일한 옵션은 동일한 mcu입니다.
dhrystone 소스 코드에서 다른 기능을 사용하여 소스 코드에서 다시 정렬하십시오. Proc_1, Proc_2, Proc_3 대신 Proc_1, Proc_3, Proc_2가됩니다. 위의 모든 작업을 다시 수행하십시오. 다시 재조정, 반복하십시오.
이 mcu를 종료하기 전에 완전히 수정되지 않은 (아마도 재 배열 기능 제외) 동일한 소스 코드의 실행 시간이 현저하게 다른 실행 시간을 가질 수 있고 또한 나타납니다.
그런 다음 컴파일러 옵션을 변경하거나 동일한 소스를 유지하고 컴파일러를 변경하면 실행 시간의 차이가 더 커집니다.
오늘날의 dhrystone 벤치 마크 또는 돌아 오는 길에서 각 플랫폼에 대해 단일 결과가 발생하는 것이 어떻게 가능합니까? 단순한 결과는 광범위한 플랫폼 중 하나였으며 실제로 플랫폼을 대표하지 않았습니다.
다른 하드웨어 플랫폼을 비교하려고하면 동일한 공급 업체 나 다른 공급 업체의 다른 MCU와 동일한 암 코어가됩니다. 팔 코어는 (같은 가정을 가정하지 않습니다) 동일한 컴파일/빌드 옵션을 가진 동일한 소스, 동일한 Verilog 컴파일 및 합성이 사용되었다고 가정하더라도 가정합니다. 팔 제공 옵션에 따라 동일한 코어 변경을 수행 할 수 있습니다. 어쨌든 공급 업체가 두 인스턴스에서 동일한 공급 업체가되거나 두 공급 업체가 동일한 코어를 래핑하는 방식은 다양합니다. 그렇다면 완전히 다른 코어를 다른 팔이나 밉 (mips) 등으로 사용하십시오. 이와 같은 프로그램을 사용하는 사람들을 비교할 때 어떤 가치를 얻을 수 있습니까?
당신은 할 수 없습니다. 당신이 할 수있는 것은 하나의 것이 다른 것보다 낫다는 착각을 일으키는 벤치 마크를 사용하는 것입니다. 한 컴퓨터는 다른 것보다 빠르며, 하나의 컴파일러는 다른 것보다 빠릅니다. 컴퓨터 또는 컴파일러를 판매하기 위해서. Sprints coverage가 Verizons의 1 % 이내입니다 ... 유용한 정보가 있습니까? 아니.
방정식에서 컴파일러를 제거하고 이들이 실제로 "CPU"와 동일한 경우, ARM의 소스와 동일한 방법으로 빌드 한 다음 동일한 방법으로 빌드해야하지만 크기는 동일해야합니다. 캐시는 그 부분이므로 캐시의 너비 또는 깊이가 사물에 영향을 미칠 수 있으므로 이미 다른 CPU 구현 일 수 있습니다. 소프트웨어에서는 16 비트 포인터 대신 16 비트 포인터 (16 비트 대신 17 비트가 필요하지만 일반적으로 할 수있는 로직은 17 비트)가 필요합니다.
어쨌든 두 플랫폼 모두에 공통적 인 주소 공간에 대해 테스트중인 코드를 컴파일하는 경우 해당 공간에 정확히 동일한 바이너리를 사용하고 필요에 따라 다른 부트 스트랩 코드를 첨부 할 수 있으며 C 라이브러리는 strcpy, 등등은 컴파일러와 정렬을 제거하여 플랫폼 간 동일한 공간에서 동일해야합니다. 이것은 경기장을 평평하게 만들지 않을 수도 있습니다.
이들이 동일한 CPU라고 생각하려면 캐시를 끄고 위의 작업을 수행하여 컴파일러 변형을 제거하십시오. 그들이 같은 것을 실행하는지보십시오. 램에 프로그램을 복사하고 램에서 실행하여 플래시 문제를 제거하십시오. 나는 당신이 플래시에서 똑같은 대기 상태로 둘 다 똑같이 클럭하도록했다고 가정합니까?
CPU가 같고 칩 공급 업체가이 두 칩을 사용하면 메모리 시스템에서 램 액세스에 대해 말하는 것과 동일한 수의 클럭을 사용하며 실제로 동일한 CPU를 사용하면 동일한 결과를 얻을 수 있습니다 최적화 (캐싱, 플래시 프리 페칭, 정렬)를 제거하여 시간을 절약 할 수 있습니다.
아마도 컴파일러와 캐시 라인에서 코드가 메모리에있는 방식과 정렬 방식이 다르거 나 훨씬 간단 할 수 있습니다. 캐시의 차이점, 히트와 미스의 차이점 작업하고 4KB는 특정 방식으로 컴파일 된 특정 프로그램에 대한 8KB보다 더 운이 좋습니다.
위의 간단한 두 명령어 루프를 사용하면 몇 가지 이유를 쉽게 알 수 있습니다 성능은 동일 시스템에 따라 달라 지므로 현대 CPU가 한 번에 8 개의 명령어를 가져오고 루프가 페치의 끝 부분에 너무 가깝게되면 프리 페치는 해당 클럭주기에 해당하는 비용을 초과하여 또 다른 8 개를 페치해야한다고 생각할 수 있습니다. 물론 두 개의 "명령어 페치 (fetch line)"를 걸치고 두 명령어를 호출하면 캐시가있는 경우에도 루프 당 더 많은 사이클이 소비됩니다.이 두 명령어가 캐시 라인에 접근 할 때 동일한 문제가 발생합니다 (테스트마다 정렬이 다름) 결국 두 명령어를 가져 오는 대신 두 개의 캐시 라인 읽기가 필요합니다. 적어도 처음으로 읽는 여분의 캐시 라인이 있습니다. 최초의 추가 시계는 정렬 작업을하면서 간단한 벤치 마크를 사용하여 볼 수 있습니다.
Michael Abrash, Assembly Language. 이 책의 github에서 빌드 할 수있는 epub/etc가 있습니다. 이 책이 나왔을 때 8088은 쓸모가 없었습니다. 8088 가지를 보았다면 완전히 그 지점을 놓치고 있습니다. 오늘날의 가장 현대적인 프로세서, 문제를 보는 방법, 테스트하는 방법, 테스트 시간을 정하는 방법, 결과를 해석하는 방법 등에 적용됩니다. 제가 지금까지 언급 한 모든 것들과 제가 언급하지 않은 이것에 대해 알고있는 모든 것들은 모두 제가이 일을 해오 던 수십 년 동안 적용된 지식들로부터 왔습니다.
다시 컴파일러, 정렬, CPU, 해당 CPU에 연결된 메모리 시스템 등을 제거하고 캐시 크기 만 변경하면 다시 다릅니다. 그런 다음 두 캐시에 대한 캐시 라인을 기준으로 한 코드의 정렬에 따라 캐시 라인이 어떻게 히트 및 미스를 가져 오는 지와 관련이 있습니다. 하나는 더 많은 것을 치고 더 적은 누락 및/또는이 특정 바이너리에 대해 더 나은 추세입니다. 함수를 재정렬하거나 nop을 추가 할 수 있습니다. 또는 부트 스트랩에서 얻을 수없는 경우 전체 함수 나 더 많은 코드 (다른 printf 등)를 바이너리의 더 낮은 주소에 추가하여 링커가 테스트중인 코드를 프로그램이 캐시 라인과 정렬되는 방식을 변경하는 다른 주소. 테스트중인 코드의 함수가 너무 커서 (구현할 수있는 몇 가지 명령어 이상), 캐시 라인에 비해보다 정교한 바이너리 조정을 얻으려면 프로그램을 수정해야합니다.
정렬을 조정하거나 재배치중인 기능을 기반으로 바이너리를 재배치하는 경우 두 플랫폼에서 실행 시간 차이가 가장 분명해야합니다.
하단 라인 벤치 마크는 실제로 많은 것을 말해주지는 않지만 결과는 긍정적 인 기쁨보다는 그들에게 부정적인 악취를 더 많이 낳습니다. 다시 작성하지 않고 특정 벤치 마크 또는 응용 프로그램을 정렬로 인해 결과를 변경하려고 할 때도 한 플랫폼에서 더 잘 수행 할 수 있습니다 (모든 것이 동일하지만 캐시의 크기 또는 완전히 다른 두 아키텍처 일 수 있음). 그리고 오프 프리 펫팅, 쓰기 버퍼링, 분기 예측 등등. 당신이 하나를 생각 해낼 수있는 모든 트릭을 추출하는 것은 x에서 y까지 다양 할 수 있으며, n에서 m까지 그리고 어쩌면 범위에 일부 중복이있을 수 있습니다. 이 두 플랫폼에 대해 캐시 크기를 제외하고는 비슷한 것을 알았습니다. 가끔 A가 B보다 빠르며 B가 A보다 빠르며 두 가지 모두에 대해 동일한 기능을 켜고 끄는 조합을 찾을 수 있기를 바랍니다. 그 비교에서./다른 애플리케이션/벤치 마크로 전환 할 때이 모든 것이 다시 시작될 때 dhrystone 결과가 테스트중인 다른 코드를 예측할 이유는 없습니다. MCU에서 중요한 유일한 프로그램은 애플리케이션의 최종 빌드입니다. 한 줄의 코드를 변경하거나 부트 스트랩에 단일 nop을 추가하는 것만으로도 한 번의 Nop에서 여러 TIMES가 더 느리게 또는 더 빠른 성능을 보일 수 있습니다.