for 루프를 사용하여 openMP를 사용하여 병렬화 된 코드가 있습니다. 지금은 여러 번 기능을 반복하고 MPI를 사용하여 기계 클러스터에 제출하여 인트라 노드를 계속 유지하면서 OpenMP로 유지하려고했습니다.openMPI와 openMP를 혼합 할 때 이상한 행동이 발생했습니다.
openMP 만 사용할 때 기대 한 속도를 얻을 수 있습니다 (절반의 시간에 두 번 프로세서/코어 수가 완료 됨). MPI를 추가하고 하나의 MPI 프로세스에만 제출하면이 속도가 향상되지 않습니다. 이 문제를 확인하기 위해 장난감 문제를 만들었지 만 여전히 같은 문제가 있습니다. 여기에 코드
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include "mpi.h"
#include <omp.h>
int main(int argc, char *argv[]) {
int iam=0, np = 1;
long i;
int numprocs, rank, namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
double t1 = MPI_Wtime();
std::cout << "!!!Hello World!!!" << std::endl; // prints !!!Hello World!!!
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Get_processor_name(processor_name, &namelen);
int nThread = omp_get_num_procs();//omp_get_num_threads here returns 1??
printf("nThread = %d\n", nThread);
int *total = new int[nThread];
for (int j=0;j<nThread;j++) {
total[j]=0;
}
#pragma omp parallel num_threads(nThread) default(shared) private(iam, i)
{
np = omp_get_num_threads();
#pragma omp for schedule(dynamic, 1)
for (i=0; i<10000000; i++) {
iam = omp_get_thread_num();
total[iam]++;
}
printf("Hello from thread %d out of %d from process %d out of %d on %s\n",
iam, np, rank, numprocs,processor_name);
}
int grandTotal=0;
for (int j=0;j<nThread;j++) {
printf("Total=%d\n",total[j]);
grandTotal += total[j];
}
printf("GrandTotal= %d\n", grandTotal);
MPI_Finalize();
double t2 = MPI_Wtime();
printf("time elapsed with MPI clock=%f\n", t2-t1);
return 0;
}
나는 -fopenmp 플래그를 사용하는 openmpi-1.8/빈/mpiC++로 컴파일하고있다. 여기 내 PBS 스크립트입니다
#PBS -l select=1:ncpus=12
setenv OMP_NUM_THREADS 12
/util/mpi/openmpi-1.8/bin/mpirun -np 1 -hostfile $PBS_NODEFILE --map-by node:pe=$OMP_NUM_THREADS /workspace/HelloWorldMPI/HelloWorldMPI
나는 또한 #PBS -l 노드 = 1 : ppn = 12로 시도했지만 동일한 결과를 얻습니다.
코어를 절반으로 사용하면 프로그램이 실제로 더 빠릅니다 (속도가 두 배 빨라짐). 코어 수를 줄이면 ncpus와 OMP_NUM_THREADS가 모두 변경됩니다. 나는 실제 작업을 증가 시키려고 노력했다. (코드에서 여기에 표시된 10^7 대신 10^10을 추가했다.) printf 명령문을 제거해 보았습니다. printf 명령문을 제거해 봤는데, 어떻게 든 느려지는지 계속 궁금해하고 있습니다. 여전히 같은 문제가 있습니다. 위로는 100 %에 가까운 모든 CPU (ncpus에서 설정된대로)를 사용하고 있음을 보여줍니다. -np = 2를 사용하여 제출하면 두 대의 컴퓨터에서 아름답게 병렬 처리되므로 MPI가 예상대로 작동하지만 OpenMP가 손상된 것 같습니다.
아이디어가 없으므로 시도해 볼 수있는 모든 것. 내가 도대체 뭘 잘못하고있는 겁니까?
나는 당신이 어떤 속도 향상을 전혀 얻지 못해서 놀랍다. 'schedule (dynamic, 1)'은이 경우 루프 스케쥴을 최악으로 선택할 수 있으며, 다중 쓰레드로부터 어레이의 이웃 요소에 끊임없이 쓰는 것은 잘못된 공유로 인해 많은 수의 캐시가 파손되게 만듭니다. 12 코어보다 6 코어에서 더 빨리 실행되는 이유입니다 (참고 : x86의 한 캐시 라인은 16 개의 int에 해당합니다). –
또한'num_threads (omp_get_num_procs())'를 사용하면 병렬 영역이 논리적 CPU 수 (즉, 코어, 결국 하이퍼 스레딩을하는 두 시간)만큼 많은 스레드에서 항상 실행되므로'OMP_NUM_THREADS'를 효과적으로 쓸 수 없게됩니다. 'top-'에'-map-by node : pe = X'는 MPI 프로세스를 노드의 첫 번째 X CPU에 바인드하기 때문에 실제로 이것을 'top'으로 보지 않을 것이다. –
각 스레드는 동일한 배열이 아닌 자체 배열에 쓰여 있어야합니다. 이것은 내가하고 싶은 일이며, 논리를 놓친 곳을 지적하십시오. 논리 CPU 수만큼 배열을 만듭니다 (omp_get_num_procs()). 각 스레드의 스레드는 해당 스레드에 특정한 배열 (이 경우 [총] [ithread])에서 작동합니다 (이 경우). – Anu