Всем доброго здоровья!
Имеется параллельная программа решения алгоритма Гаусса-Зайделя.
Указанная программа выпоняется на компьютере i7-3930k с системой Ububntu-14.04.LTS x64bit без проблем.
Все попытки запустить на системе Pelicanhpc-v2.9 завершаются ошибкой:
Код:
user@pel1:~$ mpiCC -o 1 1.cpp
user@pel1:~$ ./1
Parallel Gauss - Seidel algorithm
Enter the grid size: 10
[pel1:08516] *** Process received signal ***
[pel1:08516] Signal: Segmentation fault (11)
[pel1:08516] Signal code: Address not mapped (1)
[pel1:08516] Failing at address: 0xa0000000a
[pel1:08516] [ 0] /lib/libpthread.so.0(+0xeff0) [0x7fdea6a57ff0]
[pel1:08516] [ 1] /lib/libc.so.6(memcpy+0xa0) [0x7fdea6766bd0]
[pel1:08516] [ 2] /usr/lib/libmpi.so.0(ompi_ddt_copy_content_same_ddt+0xbd) [0x7fdea7f1686d]
[pel1:08516] [ 3] /usr/lib/libmpi.so.0(ompi_ddt_sndrcv+0x53f) [0x7fdea7f1464f]
[pel1:08516] [ 4] /usr/lib/libmpi.so.0(PMPI_Allgatherv+0x1b5) [0x7fdea7f1d6c5]
[pel1:08516] [ 5] ./1(_Z16ResultCollectionPdS_ii+0x174) [0x40a1c3]
[pel1:08516] [ 6] ./1(main+0x133) [0x40a677]
[pel1:08516] [ 7] /lib/libc.so.6(__libc_start_main+0xfd) [0x7fdea6705c8d]
[pel1:08516] [ 8] ./1() [0x409679]
[pel1:08516] *** End of error message ***
Segmentation fault
В Pelicanhpc-v2.9 присутствует тестовая программа по вычислению числа ПИ на языке фортран, выполняется без замечаний.
Привожу информацию какую смог собрать на данный момент.
Код:
user@pel1:~$ mpiCC --showme:compile
-I/usr/lib/openmpi/include \
-I/usr/lib/openmpi/include/openmpi -pthread
Код:
user@pel1:~$ mpiCC --showne:link
g++ -I/usr/lib/openmpi/include \
-I/usr/lib/openmpi/include/openmpi -pthread \
-L/usr/lib/openmpi/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl \
-Wl,--export-dynamic -lnsl -lutil -lm ?ldl
Код:
user@pel1:~$ mpiCC -g foo.cpp --showme
g++ -g foo.cpp -I/usr/lib/openmpi/include \
-I/usr/lib/openmpi/include/openmpi -pthread \
-L/usr/lib/openmpi/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl \
-Wl,--export-dynamic -lnsl -lutil -lm ?ldl
Код:
user@pel1:~$ ompi_info --all | grep wrapper
MCA pml: parameter "pml_wrapper" (current value: <none>, data source: default value)
MCA rml: parameter "rml_wrapper" (current value: <none>, data source: default value)
Код:
user@pel1:~$ ompi_info --all --parsable | grep wrapper:extra
option:wrapper:extra_cflags:-pthread
option:wrapper:extra_cxxflags:-pthread
option:wrapper:extra_fflags:-pthread
option:wrapper:extra_fcflags:-pthread
option:wrapper:extra_ldflags:
option:wrapper:extra_libs: -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl
Код:
user@pel1:~$ mpiCC -g --showme
g++ -g
Код:
user@pel1:~$ mpiCC --version --shome
g++ (Debian 4.4.5-8) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Код:
user@pel1:~$ mpiCC --version
g++ (Debian 4.4.5-8) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is no warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Построение системы MPI в скрипте создания Pelicanhpc-v2.9
Код:
# openmpi MPI
libopenmpi-dev openmpi-bin openmpi-doc
Код:
# get, build, and install Open MPI
wget http://www.open-mpi.org/software/ompi/v1.4/downloads/openmpi-$OPENMPIVERSION.tar.bz2
tar xfj openmpi-$OPENMPIVERSION.tar.bz2
cd openmpi-$OPENMPIVERSION/
./configure
make -j8 all
make install
sync
cd ../
rm -R -f openmpi*
ldconfig
sync
Код:
# support software compiled using older Open MPI
ln -s /usr/lib/openmpi/lib/libopen-rte.so.0.0.0 /usr/lib/openmpi/lib/liborte.so.0
ln -s /usr/lib/openmpi/lib/libopen-pal.so.0.0.0 /usr/lib/openmpi/lib/libopal.so.0
# support software compiled using older Open MPI
ln -s /usr/lib/openmpi/lib/libopen-rte.so.0.0.0 /usr/lib/openmpi/lib/liborte.so.0
ln -s /usr/lib/openmpi/lib/libopen-pal.so.0.0.0 /usr/lib/openmpi/lib/libopal.so.0
bailout2
fi
01BOOTSETUP
mpiCC-wrapper-data.txt
Код:
[code]# There can be multiple blocks of configuration data, chosen by
# compiler flags (using the compiler_args key to chose which block
# should be activated. This can be useful for multilib builds. See the# multilib page at:
# https://svn.open-mpi.org/trac/ompi/wiki/compilerwrapper3264
# for more information.[/code]
project=Open MPI
project_short=OMPI
version=1.4.2
language=C++
compiler_env=CXX
compiler_flags_env=CXXFLAGS
compiler=g++
extra_includes=openmpi
preprocessor_flags=
compiler_flags=-pthread
linker_flags=
libs=-lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl
required_file=
includedir=${includedir}
libdir=${libdir}
Вывод от i7-3930k с системой Ububntu-14.04.LTS x64bit
Код:
Name:~$ mpiCC prog.cpp -o prog --showme
g++ prog.cpp -o prog -I/usr/lib/openmpi/include \
-I/usr/lib/openmpi/include/openmpi -pthread \
-L/usr//lib -L/usr/lib/openmpi/lib -lmpi_cxx -lmpi -ldl -lhwloc
Код:
# Закомментирована (стр. 5 make_pelican-v2.9)
#echo "alias mpirun='mpirun -x PRELOAD=libmpi.so'" >> /home/user/.bashrc
Уважаемые, подскажите в чем причина Segmentation fault.
Где собака зарыта.За ранее спасибо!
ps.
Код:
/* Программный код параллельного приложения алгоритма Гаусса-Зейделя*/
#include <stdio.h>
#include <stdlib.h>
//#include <conio.h>
#include <time.h>
#include <math.h>
#include <mpi.h>
//#include <algorithm.h>
static int ProcNum = 0; // Number of available processes
static int ProcRank = -1; // Rank of current process
// Function for distribution of the grid rows among the processes
void DataDistribution(double* pMatrix, double* pProcRows, int RowNum,
int Size) {
int *pSendNum; // Number of elements sent to the process
int *pSendInd; // Index of the first data element sent to the process
int RestRows=Size;
// Alloc memory for temporary objects
pSendInd = new int [ProcNum];
pSendNum = new int [ProcNum];
// Define the disposition of the matrix rows for current process
RowNum = (Size-2)/ProcNum+2;
pSendNum[0] = RowNum*Size;
pSendInd[0] = 0;
for (int i=1; i<ProcNum; i++) {
RestRows = RestRows - RowNum + 2;
RowNum = (RestRows-2)/(ProcNum-i)+2;
pSendNum[i] = (RowNum)*Size;
pSendInd[i] = pSendInd[i-1]+pSendNum[i-1]-Size;
}
// Scatter the rows (Разброс строк)
MPI_Scatterv(pMatrix , pSendNum, pSendInd, MPI_DOUBLE, pProcRows,
pSendNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);
delete []pSendInd;
delete []pSendNum;
}
// Function for computational process termination
void ProcessTermination (double* pMatrix, double* pProcRows) {
if (ProcRank == 0)
delete [] pMatrix;
delete [] pProcRows;
}
// Function for formatted matrix output
void PrintMatrix(double *pMatrix, int RowCount, int ColCount){
int i,j; // Loop variables
for(int i=0; i < RowCount; i++) {
for(j=0; j < ColCount; j++)
printf("%7.4f ", pMatrix[i*ColCount+j]);
printf("\n");
}
}
// Function for the execution of the Gauss-Seidel method iteration
double IterationCalculation(double* pProcRows, int Size, int RowNum) {
int i, j; // Loop variables
double dm, dmax,temp;
dmax = 0;
for (i = 1; i < RowNum-1; i++)
for(j = 1; j < Size-1; j++) {
temp = pProcRows[Size * i + j];
pProcRows[Size * i + j] = 0.25 * (pProcRows[Size * i + j + 1] +
pProcRows[Size * i + j - 1] +
pProcRows[Size * (i + 1) + j] +
pProcRows[Size * (i - 1) + j]);
dm = fabs(pProcRows[Size * i + j] - temp);
if (dmax < dm) dmax = dm;
}
return dmax;
}
// Function for testing the data distribution
void TestDistribution(double* pMatrix, double* pProcRows, int Size,
int RowNum) {
if (ProcRank == 0) {
printf("Initial Matrix: \n");
PrintMatrix(pMatrix, Size, Size);
}
MPI_Barrier(MPI_COMM_WORLD);
for (int i=0; i<ProcNum; i++) {
if (ProcRank == i) {
printf("\nProcRank = %d \n", ProcRank);
//fprintf(" Matrix Stripe:\n");
PrintMatrix(pProcRows, RowNum, Size);
}
MPI_Barrier(MPI_COMM_WORLD);
}
}
// Function for simple setting the grid node values
void DummyDataInitialization (double* pMatrix, int Size) {
int i, j; // Loop variables
double h = 1.0 / (Size - 1);
// Setting the grid node values
for (i=0; i<Size; i++) {
for (j=0; j<Size; j++)
if ((i==0) || (i== Size-1) || (j==0) || (j==Size-1))
pMatrix[i*Size+j] = 100;
else
pMatrix[i*Size+j] = 0;
}
}
// Function for memory allocation and initialization of grid nodes
void ProcessInitialization (double* &pMatrix, double* &pProcRows, int &Size,
int &RowNum, double &Eps) {
int RestRows; // Number of rows, that haven?t been distributed yet
// Setting the grid size
if (ProcRank == 0) {
do {
printf("\nEnter the grid size: ");
scanf("%d", &Size);
if (Size <= 2) {
printf("\n Size of grid must be greater than 2! \n");
}
if (Size < ProcNum) {
printf("Size of grid must be greater than"
"the number of processes! \n ");
}
}
while ( (Size <= 2) || (Size < ProcNum));
// Setting the required accuracy
do {
// cout << "\nEnter the required accuracy: ";
printf("Enter the required accuracy: ");
//cin >> &Eps;
scanf("%lf", &Eps);
//cout << "Chosen accuracy = %lf";
//cout << Eps;
printf("\nChosen accuracy = %lf", Eps);
if (Eps <= 0)
//cout << "Accuracy must be greater than 0!" << endl;
printf("\nAccuracy must be greater than 0!\n");
}
while (Eps <= 0);
///Eps=0.25;
}
MPI_Bcast(&Size, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Bcast(&Eps, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
// Define the number of matrix rows stored on each process
RestRows = Size;
for (int i=0; i<ProcRank; i++)
RestRows = RestRows-RestRows/(ProcNum-i);
RowNum = (RestRows-2)/(ProcNum-ProcRank)+2;
// Memory allocation
pProcRows = new double [RowNum*Size];
// Define the values of initial objects? elements
if (ProcRank == 0) {
// Initial matrix exists only on the pivot process
pMatrix = new double [Size*Size];
// Values of elements are defined only on the pivot process
DummyDataInitialization(pMatrix, Size);
}
}
// Function for exchanging the boundary rows of the process stripes
void ExchangeData(double* pProcRows, int Size, int RowNum) {
MPI_Status status;
int NextProcNum = (ProcRank == ProcNum-1)? MPI_PROC_NULL : ProcRank + 1;
int PrevProcNum = (ProcRank == 0)? MPI_PROC_NULL : ProcRank - 1;
// Send to NextProcNum and receive from PrevProcNum
MPI_Sendrecv(pProcRows + Size * (RowNum - 2),Size, MPI_DOUBLE,
NextProcNum, 4, pProcRows, Size, MPI_DOUBLE, PrevProcNum, 4,
MPI_COMM_WORLD, &status);
// Send to PrevProcNum and receive from NextProcNum
MPI_Sendrecv(pProcRows + Size, Size, MPI_DOUBLE, PrevProcNum, 5,
pProcRows + (RowNum - 1) * Size, Size,MPI_DOUBLE, NextProcNum, 5,
MPI_COMM_WORLD, &status);
}
// Function for the parallel Gauss - Seidel method
void ParallelResultCalculation (double *pProcRows, int Size, int RowNum,
double Eps, int &Iterations) {
double ProcDelta,Delta;
Iterations=0;
do {
Iterations++;
// Exchanging the boundary rows of the process stripe
ExchangeData(pProcRows, Size,RowNum);
// The Gauss-Seidel method iteration
ProcDelta = IterationCalculation(pProcRows, Size, RowNum);
// Calculating the maximum value of the deviation
MPI_Allreduce(&ProcDelta, &Delta, 1,MPI_DOUBLE, MPI_MAX,
MPI_COMM_WORLD);
} while ( Delta > Eps);
}
// Function for gathering the result vector
void ResultCollection(double *pMatrix, double* pProcResult, int Size,
int RowNum) {
int *pProcRows;
int *pReceiveNum; // Number of elements, that current process sends
int *pReceiveInd; // Index of the first element of the received block
int RestRows = Size;
int i; // Loop variable
// Alloc memory for temporary objects
pReceiveNum = new int [ProcNum];
pReceiveInd = new int [ProcNum];
// Define the disposition of the result vector block of current processor
pReceiveInd[0] = 0;
RowNum = (Size-2)/ProcNum+2;
pReceiveNum[0] = RowNum*Size;
for ( i=1; i < ProcNum; i++) {
RestRows = RestRows - RowNum + 1;
RowNum = (RestRows-2)/(ProcNum-i)+2;
pReceiveNum[i] = RowNum*Size;
pReceiveInd[i] = pReceiveInd[i-1]+pReceiveNum[i-1]-Size;
}
// Gather the whole result vector on every processor
MPI_Allgatherv(pProcRows, pReceiveNum[ProcRank], MPI_DOUBLE, pMatrix,
pReceiveNum, pReceiveInd, MPI_DOUBLE, MPI_COMM_WORLD);
// Free the memory
delete [] pReceiveNum;
delete [] pReceiveInd;
}
// Function for the serial Gauss ? Seidel method
void SerialResultCalculation(double *pMatrixCopy, int Size, double Eps,
int &Iter){
int i, j; // Loop variables
double dm, dmax,temp;
Iter = 0;
do {
dmax = 0;
for (i = 1; i < Size - 1; i++)
for(j = 1; j < Size - 1; j++) {
temp = pMatrixCopy[Size * i + j];
pMatrixCopy[Size * i + j] = 0.25 * (pMatrixCopy[Size * i + j + 1] +
pMatrixCopy[Size * i + j -1] +
pMatrixCopy[Size * (i + 1) + j] +
pMatrixCopy[Size * (i - 1) + j]);
dm = fabs(pMatrixCopy[Size * i + j] - temp);
if (dmax < dm) dmax = dm;
}
Iter++;
}
while (dmax > Eps);
}
// Function to copy the initial data
void CopyData(double *pMatrix, int Size, double *pSerialMatrix) {
(pMatrix, pMatrix + Size, pSerialMatrix);
}
// Function for testing the computation result
void TestResult(double* pMatrix, double* pSerialMatrix, int Size,
double Eps) {
int equal = 0; // =1, if the matrices are not equal
int Iter;
if (ProcRank == 0) {
SerialResultCalculation(pSerialMatrix, Size, Eps, Iter);
for (int i=0; i<Size*Size; i++) {
if (fabs(pSerialMatrix[i]-pMatrix[i]) >= Eps)
equal = 1;break;
}
if (equal == 1)
printf("The results of serial and parallel algorithms"
"are NOT identical. Check your code.");
else
printf("The results of serial and parallel algorithms"
"are identical.");
}
}
// Function for setting the grid node values by a random generator
void RandowmDataInitialization (double* pMatrix, int Size) {
int i, j; // Loop variables
srand(unsigned(clock()));
// Setting the grid node values
for (i=0; i<Size; i++) {
for (j=0; j<Size; j++)
if ((i==0) || (i== Size-1) || (j==0) || (j==Size-1))
pMatrix[i*Size+j] = 100;
else
pMatrix[i*Size+j] = rand()/double(1000);
}
}
int main(int argc, char* argv[]) {
double* pMatrix; // Matrix of the grid nodes
double* pProcRows; // Stripe of the matrix on current process
double* pSerialMatrix; // Result of the serial method
int Size; // Matrix size
int RowNum; // Number of rows in matrix stripe
double Eps; // Required accuracy
int Iterations; // Iteration number
double currDelta, delta;
setvbuf(stdout, 0, _IONBF, 0);
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);
MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);
if(ProcRank == 0) {
printf("Parallel Gauss - Seidel algorithm \n");
fflush(stdout);
}
// Process initialization
ProcessInitialization (pMatrix,pProcRows,Size,RowNum,Eps);
// Creating the copy of the initial data
if (ProcRank == 0) {
pSerialMatrix = new double[Size*Size];
CopyData(pMatrix, Size, pSerialMatrix);
}
// Data distribution among the processes
DataDistribution(pMatrix, pProcRows, Size,RowNum);
// Paralle Gauss-Seidel method
ParallelResultCalculation(pProcRows, Size,RowNum,Eps, Iterations);
//TestDistribution(pMatrix, pProcRows, Size,RowNum);
// Gathering the calculation results
ResultCollection(pProcRows, pMatrix, Size, RowNum);
TestDistribution(pMatrix, pProcRows, Size,RowNum);
// Printing the result
printf("\n Iter %d \n", Iterations);
printf("\nResult matrix: \n");
if (ProcRank==0) {
//TestResult(pMatrix,Size,pMatrixCopy,Eps);
PrintMatrix(pMatrix,Size,Size);
}
// Process termination
if (ProcRank == 0) delete []pSerialMatrix;
ProcessTermination(pMatrix, pProcRows);
MPI_Finalize();
}