CUDA에서 병렬 병합 알고리즘을 구현하려고합니다. 이 알고리즘은 하나의 스레드 블록에서 실행되도록 설계되었습니다. 기본 개념은 두 입력 시퀀스에서 각 요소의 전역 순위를 계산하는 것입니다. 이 두 입력 시퀀스가 정렬되기 때문에 요소의 전역 순위는 원래 시퀀스의 인덱스와 이진 검색에 의해 계산 된 다른 시퀀스의 순위와 같습니다. 이러한 알고리즘을 구현하는 가장 좋은 전략은 두 개의 시퀀스를 공유 메모리에로드하여 전역 메모리 읽기를 줄이는 것입니다. 그러나 공유 메모리를 사용하지 않고 공유 메모리를 사용하는 구현 버전과 공유 메모리를 사용하지 않는 구현 버전을 비교했을 때 성능 향상을 볼 수 없었습니다. 내가 뭔가 잘못하고 있는지 궁금해.공유 메모리가있는 CUDA에서 병렬 병합을 구현해도 성능이 향상되지 않습니다.
하드웨어 : GeForce GTX 285, Linux x86_64. 두 구현에 대해 두 개의 1024 요소 시퀀스를 병합하는 시간은 약 0.068672ms입니다.
__global__ void localMerge(int * A, int numA,int * B,int numB,int * C){
extern __shared__ int temp[]; // shared memory for A and B;
int tx=threadIdx.x;
int size=blockDim.x;
int *tempA=temp;
int *tempB=temp+numA;
int i,j,k,mid;
//read sequences into shared memory
for(i=tx;i<numA;i+=size){
tempA[i]=A[i];
}
for(i=tx;i<numB;i+=size){
tempB[i]=B[i];
}
__syncthreads();
//compute global rank for elements in sequence A
for(i=tx;i<numA;i+=size){
j=0;
k=numB-1;
if(tempA[i]<=tempB[0]){
C[i]=tempA[i];
}
else if(tempA[i]>tempB[numB-1]){
C[i+numB]=tempA[i];
}
else{
while(j<k-1){
mid=(j+k)/2;
if(tempB[mid]<tempA[i]){
j=mid;
}
else{
k=mid;
}
}
//printf("i=%d,j=%d,C=%d\n",i,j,tempA[i]);
C[i+j+1]=tempA[i];
}
}
//compute global rank for elements in sequence B
for(i=tx;i<numB;i+=size){
j=0;
k=numA-1;
if(tempB[i]<tempA[0]){
C[i]=tempB[i];
}
else if(tempB[i]>=tempA[numA-1]){
C[i+numA]=tempB[i];
}
else{
while(j<k-1){
mid=(j+k)/2;
if(tempA[mid]<=tempB[i]){
j=mid;
}
else{
k=mid;
}
}
//printf("i=%d,j=%d,C=%d\n",i,j,tempB[i]);
C[i+j+1]=tempB[i];
}
}
}
그냥 오해하지 않았으므로이 커널을 1 블록으로 실행하고 있습니까? – talonmies
많은 루프와 브랜칭 구문 때문에 나는 cuda 버전이 느리지 않다는 사실에 놀랐습니다. 또한 병렬 아키텍처를 다루는 경우에는 비트 코드 병합이 직렬 코드에서 구현이 느려지더라도 진행할 수있는 방법입니다. –
@talonmies 예. 하나의 스레드 블록으로 커널을 실행합니다. – xhe8