2014-04-28 3 views
0

저수준 메모리 최적화에 대해 많이 알지는 않지만 rbg32 데이터를 보유하는 서명되지 않은 char 배열에서 메모리 액세스를 최적화하는 방법을 찾으려고합니다.RGB32 바이트 배열 메모리 액세스 최적화

데이터의 평균 영역을 필요로하는 DirectShow 변환 필터 (CTransInPlaceFilter)를 만들고 있습니다. 나에게 주어진 데이터는 rgb32 형식 (B G R 0xFF B G R 0xFF B G R 0xFF etc)입니다. 데이터를 반복하고 평균 적색, 녹색 및 파란색 채널을 계산 중입니다.

바이트 배열의 데이터를 역 참조 할 때 비디오 재생이 CPU를 실행하고 액세스하지 않고 CPU를 실행하므로 CPU가 많은 작업을 수행하지 않습니다.

게시물 모음을 읽은 후에는 CPU 대역폭 병목 현상에 대한 메모리라고 생각합니다. 나는 3 역 참조 선없이 동영상을 실행할 때

HRESULT CFilter :: 변환 (의 IMediaSample * pSample) {그래서

BYTE* data = NULL; 
pSample->GetPointer(&data); 

if (mVideoType == MEDIASUBTYPE_RGB32) { 
    Rect roi(0, 0, 400, 400);   // Normally this is dynamic 
    int totalPixels = roi.width * roi.height; 

    // Find the average color 
    unsigned int totalR = 0, totalG = 0, totalB = 0; 
    for (int r = 0; r < roi.height; r++) { 
     int y = roi.y + r; 
     BYTE* pixel = data + (roi.x + y * mWidth) * 4;  // 4 bytes per pixel 

     for (int c = 0; c < roi.width; c++) { 
      totalB += *pixel;   // THESE 3 LINES IS THE ISSUE 
      totalG += *(++pixel); 
      totalR += *(++pixel); 
      pixel++; 
     } 
    } 
    int meanR = (int)floor(totalR/totalPixels); 
    int meanG = (int)floor(totalG/totalPixels); 
    int meanB = (int)floor(totalB/totalPixels); 
    // Does work with the averaged data 
} 
return S_OK; } 

: 여기

은 변환 함수에 대한 코드입니다 나는 대략 10-14 % cpu 사용법을 얻는다. 그 선으로 나는 30-34 % cpu 사용법을 얻는다.

또한 데이터에 액세스하기 위해 버퍼에 데이터를 복사하려고했습니다.

mempy(mData, data, mWidth * mHeight * 4);  // mData is only allocated once in constructor 
... 
totalB += mData[x + y * mWidth]; 

cpu 사용량이 22-25 %가되었습니다.

CPU 사용량을 다시 10 분으로 줄일 수 있습니까? 어떻게 든 데이터에 훨씬 빠르게 액세스 할 수 있습니까? asm을 사용해 볼까요?

기타 정보 : 비디오는 GraphEdit을 사용하여 내 필터를 테스트하는 10 비트 1280 X 720입니다. 내 필터가 원본 이미지를 변경하지 않으므로 복사되지 않습니다. 도움이된다면이 프로세스를 스레드로 처리 할 수 ​​있습니다.

미리 감사드립니다.

편집 :

는 더 많은 정보를 위해, 나는 DirectShow를 그래프를 추가했다. 비디오는 10 비트이지만 Lav 필터는 RGB32 (8 비트)를 나에게 넘깁니다. 그것은 디버그 빌드, 릴리스 속도 (결국 내가 릴리스 빌드 컴파일됩니다).

enter image description here

나는 2 개 가지 방법을 실행 (앞서 언급)과 경과 시간을 벤치마킹. 역 참조를 사용하면 변환이 실행될 때마다 약 0.126208 밀리 초가됩니다. 역 참조가 없으면 0.009 밀리 초가됩니다.

나는 또한 CPU 사용량을 변경하지 않은

for (int c = 0; c < roi.width; c += 4) { 
    totalB += pixel[c] + pixel[c + 3] + pixel[c + 6] + pixel[c + 9]; 
    totalG += pixel[c + 1] + pixel[c + 4] + pixel[c + 7] + pixel[c + 10]; 
    totalR += pixel[c + 2] + pixel[c + 5] + pixel[c + 8] + pixel[c + 11]; 
} 

이를 수행하여 루프를 줄이기 위해 노력하고 경과 시간은 여전히 ​​주위 0입니다.12

편집 2 :

나는 모든 종속성 및 릴리스의 프로젝트 자체를 구축하고 내가 같은 결과를 얻을. 여전히 매우 느린 액세스.

+1

상당히 느립니다. 일반적으로 여기에 SIMD 최적화가 필요합니다. 또한 10 비트 비디오라고 말하면서 8 비트 연산을 수행하므로 추가 변환기/디코더가 추가됩니다. –

+0

: http://ideone.com/lVmT2e – Brandon

+1

이것은 디버그 또는 릴리스 빌드입니까? –

답변

1

나는이 문제를 해결했다. 그래서 문제는 데이터가 비디오 메모리의 데이터를 가리키는 포인터라는 것입니다. 데이터를 사용하여 비디오에서 컴퓨터 RAM으로 전송하여 메모리 대역폭 오류가 발생했습니다. 한 번에 모든 데이터를 복사 (memcpy)가 빠르지 만 여전히 매우 느립니다. 대신 비디오 메모리에서 컴퓨터 메모리로 데이터를 효율적으로 복사하기 위해 특정 Intel SSE4 명령을 사용해야했습니다.

나는 this file (gpu_memcpy)을 사용했습니다. 그것은 memcpy와 비슷한 기능을 포함하고 있지만 GPU를 사용하여 작업을 수행합니다. 복사가 완료되면 훨씬 빠르며 데이터 액세스는 평소와 같이 빠릅니다.