2013-08-19 3 views
2

저는 기본 이미지 내에 약 35 개의 하위 이미지 또는 패턴을 찾으려고하는 CUDA 프로그램을 작성하고 있습니다. 각 하위 이미지 (패턴)는 기본 이미지의 작은 영역 (예 : 10x10 픽셀 창)에만 존재할 수 있습니다. 하위 이미지의 크기는 1000에서 10000 픽셀까지 다양합니다. 기본 이미지는 640x480 픽셀입니다.여러 개의 작은 컨볼 루션 : 이미지 처리

전 컨볼 루션 결과는 그 일치하는 것으로 간주되는 것보다, 임계치보다 작은 상기베이스 화상의 서브 섹션면, 서브 영상을 컨벌루션함으로써 이것을한다. 하위 이미지 당 약 100 편의 컨볼 루션을 수행해야합니다 (허용 가능한 위치의 10x10 창만 확인하기 때문에).

첫 번째 질문 : 이것이 구현되었으며 오픈 소스에서 사용할 수 있습니까?

두 번째 질문 : 더 나은 구현 전략은 무엇입니까?

  1. 거친 나뭇결 각 CUDA 스레드가 기본 이미지 내에서 서브 이미지의 완전 컨볼 루션을 수행합니다. 각 하위 이미지 및 위치에 대해 하나의 CUDA 스레드가 있습니다.
  2. 미세 그레인 :베이스 이미지의 적절한 픽셀만큼 부 화상 그래서 CUDA 실 배수 화소 각각 CUDA 스레드 회선의 하나 개의 구성 요소 (픽셀)를 계산한다. 그런 다음 syncblock()을 사용하여 이러한 배수를 더합니다.

업데이트 : 나는 두 가지 접근 방식을 TRID. 가장 좋은 방법은 더 큰 하위 이미지를 더 작은 하위 이미지로 나누는 방법 중 하나의 변형이라고 생각합니다. 이제 모든 하위 이미지는 거의 같은 크기입니다 (예 : 1024 픽셀). 그런 다음 각 CUDA 스레드는 단일 위치에 대해 전체 컨볼 루션을 수행합니다. 끝나면 모든 결과를 호스트에 보내고 주인은 중간 조각을 다시 조립할 책임이 있습니다 (작은 조각으로 분할 된 하위 이미지의 경우). 이점은 모든 CUDA 스레드가 동일한 양의 작업을 수행한다는 것입니다. 이것은 서브 이미지의 크기가 다양하기 때문에 문제가되는 두 번째 방식보다 두 배 빠르다.

+0

당신이 확인 했 여기에 좋은 백서를 찾을 수 있을까? – kangshiyin

+0

'convolutionSeparable'과'convolutionTexture' 샘플을 보셨습니까? 왜 컨볼 루션을 수행하기 위해 FFT를 사용하지 않는지 ('convolutionFFT2D' 예제 참조)? 행렬이 FFT에 비해 너무 작습니까? 이 경우 CUDA에서 작은 행렬의 FFT를 빠르게 계산하는 방법이 중요 할 수 있습니다. 마지막으로 동적 병렬 처리를 고려하고 있습니까? 후자의 두 가지 경우, [CUDA를 사용하여 여러 개의 작은 행렬을 조합하는 최선의 방법]에 대한 내 대답을 살펴보십시오 (http://stackoverflow.com/questions/17955403/best-approach-for-convolution-of-multiple- 작은 매트릭스 - 사용 - cuda). – JackOLantern

+0

OpenCV는 이러한 기능을 제공하지만 OpenCV는 CUDA로 구현 되었습니까? 나는 이미 시리얼 C 코드를 가지고 있으며, 그것은 사소한 것이다. 그러나 나는 속도를위한 CUDA 구현을 원한다. –

답변

1

각 하위 이미지 및 위치에 대해 1 개의 큐다 스레드 블록 (여러 개의 큐다 스레드 포함)을 사용하는 것이 좋습니다. 당신의 서브 이미지의 크기가 다르므로

은 일괄 처리는 1 커널의 모든 서브 이미지는 좋은 선택이 될 수 없습니다. 하위 이미지의 전체 컨볼 루션을 기본 이미지로 수행하고 각 하위 이미지에 대해 35 번 호출하도록 커널을 설계 할 수 있습니다. 커널

는 그리드 그 수가 허용 위치의 수와 동일한 다수의 스레드 블록을 포함한다. 그런 다음 각 스레드 블록은 하위 이미지와 기본 이미지의 주어진 위치 사이에있는 픽셀의 배수의 합계를 계산합니다.

이 가장 큰 차이점 2. 전략과 유사하다 각 스레드는 여러 개의 픽셀을 계산할 수 있으며 커널은 전역 메모리를 통해 스레드 블록 사이의 동기화를 필요로하지 않는다 요약을 수행하는 하나의 스레드 블록을 사용합니다.

하위 이미지에 2000 픽셀이 있다고 가정하면 허용되는 위치는 10x10입니다. 100 개의 블록을 포함하는 커널을 만들 수 있습니다. 각 블록에는 256 개의 스레드가 들어 있습니다. 블록 내의 256 개의 스레드는 2000 배수의 픽셀의 병렬 합계를 수행합니다.

UPDATE

귀하의 제안 방식은 2 문제, 커널 당

  1. 너무 적은 수의 스레드가있을 수 있습니다.앞에서 설명한 것처럼 커널은 허용 가능한 위치에 대해 10x10 = 100 스레드를 가질 수 있으며 각 스레드는 약 1024 배의 픽셀을 합산합니다. 일반적으로 GPU를 완벽하게 활용하려면 커널에 적어도 32 개의 스레드 블록과 블록 당 64 ~ 256 개의 스레드가 필요할 수 있습니다.
  2. 더 커널은 좋은 선택이 아니다 그래서 작은 것들로 서브 이미지를 분할, 자주 실행 오버 헤드와 낮은 속도 시작 이상을 의미한다.

바이너리 트리 형 병렬 환원 실제로 빠른 선형 후 환원된다. 여기에 병렬 감소 샘플 코드

http://docs.nvidia.com/cuda/cuda-samples/index.html#cuda-parallel-reduction

및 OpenCV의 비슷한 기능을 provieds 경우

+0

이 방법을 시도했습니다. 합리적이지만 문제는 각 CUDA 스레드 블록에 대해 기본적으로 1024 개의 스레드가있는 모든 결과를 이진 트리에 추가해야한다는 것입니다. 나는 이것이 더 느린 방법이라고 생각한다. 원래의 질문에 대한 나의 업데이트를보십시오. –

+0

@JB_User 방법 1에서 35 개의 하위 이미지에 대해 35 회 또는 35 개의 모든 하위 이미지에 대해 한 번만 커널을 시작합니까? – kangshiyin

+0

아직 완전히 코딩되지 않았습니다. 나는 소수의 커널 (5 ~ 10 개)을 커널의 서브셋으로 시작한다고 생각한다. 35 개의 커널은 분할 된 커널이 모두 같은 크기가되도록 분할 할 때 100 개 이상의 커널과 같아집니다. –

관련 문제