2012-09-25 3 views
1

와 루프 중첩 된 I가 자바에 다음 코드 : 당신이 거기에 진짜 논리를 검색해서는 안는 + = assignement

float in[][] = new float[2][2]; 

float B[] = new float[2]; 
float A[] = new float[2]; 
float res[] = new float[A[0].length]; 

for(float r : res){ 
    r = 0; 
} 

for (int i = 0; i < A[0].length; i++) { 
    for (int j = 0; j < B[0].length; j++) { 
     res[i] += A[j] * in[j][i]; 
} 

내가 가장 그것을 단순화 :).

루프의 + = 문 때문에 CUDA에서이를 변환하는 데 몇 시간의 시간이 걸립니다.

나는 이런 식으로 뭔가 시작 :

extern "C" 
__global__ void filter(float* in, float* A, float* B, float* res, int in_size){ 

    unsigned int x = blockIdx.x*blockDim.x + threadIdx.x; 
    unsigned int y = blockIdx.y*blockDim.y + threadIdx.y; 

    res[x] = A[y] * in[x + y * in_width]; 

} 

하지만 빨리 때문에 같은 변수를 설정하려고 모든 스레드 작동하지 수 깨달았다.

나는 내적 in this presentation, 의 예를 읽을 수 있지만 난 정말에 대한 두 가지 차원의 나의 필요와 그 적응하는 방법을 볼 수 없습니다.

나는 완벽한 솔루션을 요구하지 않지만, 어떤 방향이라도 분명히 높이 평가 될 것입니다.

Thx,

답변

1

너무 많은 CUDA가 내 머리를 죽였습니다.

커널 내부 루프 중 하나를 풀어서 부분적인 해결책을 찾았습니다. 여기 그것은 지금의 모습 :

extern "C" 
__global__ void filter(float* in, float* A, float* res, const int in_width, const int sizeB){ 
    unsigned int x = blockIdx.x*blockDim.x + threadIdx.x; 
    int i = 0; 

    for(i = 0; i < sizeB; i++){ 
     res[x] += A[i] * in[i + x * in_width]; 
    } 

} 

내가 더 잘 찾을 수 있습니다 확신합니다,하지만 난 오늘 :

+0

모든 스레드와 함께 res를 증가 시키면, 이것 역시 작동하지 않아야합니다. 방금 떠있는 경우 atomics를 사용할 수 있습니다 (느려야합니다). 그렇지 않으면 모든 블록에 대해 적절한 이진 트리 감소를 구현 한 다음 CPU에서 블록 합계를 합산 할 수 있습니다. – Reguj

+0

작동하지 않습니다. 동일한 스레드에 대한 루프의 요소를 증가시키고 있습니다. 이 경우 각 x는 단일 스레드에 해당하므로 루프가 안전합니다. 단점은 각 스레드가 루프를 수행해야한다는 것입니다. 따라서 프로세스를 절반으로 최적화했습니다. – jlengrand

+1

처음 병렬화하는 방법처럼 보입니다. res 배열을 0으로 초기화해야합니다.이 커널 외부에서 수행 중이라고 가정합니다. res [x] = 0을 넣는 것이 더 빠를 것입니다. 커널 내부 루프. 다음은 최적화를위한 것입니다 ... – harrism

0

당신은 곱셈 작업 A를 분할 할 수 있습니다이 스틱 것 같아요 [j] * in [j] [i]를 A [0] .length * B [0] .length 스레드로 나누고 공유 메모리를 사용하여 NVIDIA sdk의 축소 샘플과 같이 곱셈 결과를 요약 할 수 있습니다.

+0

그러면 sizeA * sizeB 배열이 필요합니다. 내가 거대한 테이블을 가지고 일할 때 문제가 될지도 모른다. – jlengrand