빌더(TWx) 님이 쓰신 글 :
: 음? 님이 쓰신 글 :
: : 델파이7 데모파일 다운받아 보려니 없네요?
: :
: :
: : 델파이11 님이 쓰신 글 :
: : :
https://cafe.naver.com/delmadang?iframe_url_utf8=%2FArticleRead.nhn%253Fclubid%3D10382011%2526articleid%3D935%2526referrerAllArticles%3Dtrue
: : :
: : : 최신컴파일러가 CPU 확장명령어(MMX, SSE) 지원해서 그런가봐요
: : :
: : : 델파이7에서 델파이 11로 빨리 바꿔야 할 듯 하군요 ^^
: : :
: : :
:
:
: 답변:
:
:
: 첨부했던 파일을 삭제한 것은.... 작성되어 있는 글이 터무니 없이 황당한 광고성 글 같아서 였던 거고...
:
: Delphi11_Demo.rar는 데모 제작자의 원본 파일이고, Delphi7_Test.rar는 다른 방식으로 구현해서 첨부한 파일이니
: 비교해 보세요.
:
:
: CPU에 부하를 크게 주게끔 창을 최대화 해서 비교해 보면...
:
: 오히려 Delphi7 데모가 더 나은 성능을 보이기도 하는데...
:
:
: 어떤 방식으로 알고리즘을 구현하느냐의 구현방식에 따른 차이에 불과한 것일 뿐... 컴파일러가 달라서 그런 건 사실이 아니지요.
:
:
: 컴파일러가 달라서 25배 성능 차이? 한마디로.... 넌센스.
:
:
:
:
이미지 픽셀 데이타를 고속으로 처리하는 게 필요하다면... VC++ 컴파일러 쓰는 걸 추천 합니다.
예를 들어서 RGB32 이미지 데이타를 고속으로 그레이 스케일로 컨버전 할 필요가 있다면...
다음과 같이 최신 CPU가 지원해 주고 있는 AVX512 인스트럭션 확장 셋을 이용해서 VC++ 컴파일러로 작성할 수 있는데...
#include <immintrin.h>
// VC++ 2022 컴파일러
void Rgb32ToGray(const RGB_PIXEL* pRgbSrcPixels, uint8_t* pDest, const float coef[4], size_t nPixels )
{
__m512 coefR = _mm512_set1_ps(coef[0]);
__m512 coefG = _mm512_set1_ps(coef[1]);
__m512 coefB = _mm512_set1_ps(coef[2]);
__m512i Mask = _mm512_set1_epi32(0x000000ff);
__m512 packed_0_5 = _mm512_set1_ps(0.5f);
__m512 packed_255 = _mm512_set1_ps(255.0f);
const size_t nElements = 16;
for (size_t i = 0; i < nPixels; i += nElements) {
// Load next block
__m512i pixel_vals = _mm512_load_si512((__m512i*)&pRgbSrcPixels[i]);
// De-interleave
__m512i pixelsR = pixel_vals;
__m512i pixelsG = _mm512_srli_epi32(pixel_vals, 8);
__m512i pixelsB = _mm512_srli_epi32(pixel_vals, 16);
__m512i upixelR = _mm512_and_si512(pixelsR, Mask);
__m512i upixelG = _mm512_and_si512(pixelsG, Mask);
__m512i upixelB = _mm512_and_si512(pixelsB, Mask);
__m512 fpixelR = _mm512_cvtepi32_ps(upixelR);
__m512 fpixelG = _mm512_cvtepi32_ps(upixelG);
__m512 fpixelB = _mm512_cvtepi32_ps(upixelB);
fpixelR = _mm512_mul_ps(fpixelR, coefR);
fpixelG = _mm512_mul_ps(fpixelG, coefG);
fpixelB = _mm512_mul_ps(fpixelB, coefB);
__m512 ps = _mm512_add_ps(fpixelR, fpixelG);
__m512 vgs = _mm512_add_ps(fpixelB, ps);
// Round and clip grayscale pixel values
vgs = _mm512_add_ps(vgs, packed_0_5);
vgs = _mm512_min_ps(vgs, packed_255);
__m512i pixels32 = _mm512_cvtps_epi32(vgs);
__m128i pixels8 = _mm512_cvtusepi32_epi8(pixels32);
// Save converted gray scale pixels
_mm_store_si128((__m128i*) & pDest[i], pixels8);
}
}
위와 같이 최신 CPU가 지원하고 있는 AVX512 명령어 확장셋을 Inline Assembly 필요 없이
VC++로 구현 할 수 있지요. (512비트 크기의 확장 레지스터를 사용하므로 고속 연산이 가능)
수작업으로 작성된 Inline Assembly 코드와 달리, intrinsic 으로 C++ 컴파일러 차원에서
직접 지원하는 거라서 loop unroll 까지 코드 최적화가 작동하게 됍니다.
Visual Studio 2022 IDE 자체적으로 지원해 주고 있는 Performance 프로파일링으로 성능평가해서
필요에 맞게 loop unroll 을 보정해 주면 되는 거고.
AVX512 명령 셋과 CPU 아키텍쳐를 디테일하게 알고 있으면 위와 같은 식으로 구현하면 되고,
그렇지 않다면 VC++ 컴파일 옵션에서 AVX512 명령 셋을 사용하도록 지정해서, 조건에 맞을 경우
컴파일러가 AVX512 확장 인스트럭션 셋을 생성하도록 해 줄 수도 있지요.