2013-12-20 5 views
5

Я пишу небольшой тестовый код для диагонализации параллельной матрицы с использованием алгоритма разделения и покоя ScaLAPACK PDSYEVD на C. Однако я новичок в ScaLAPACK и, глядя на источник, кажется довольно страшным количеством переменные, для которых я не мог найти хороших примеров. Тип матриц, которые мне нужно диагонализировать, являются реальными, симметричными, довольно разреженными и размером ~ 1000х1000.Диагональ матрицы скайпака (pdsyevd)

Простой (последовательный) LAPACK основе код выглядит следующим образом:

/* "matrix diagonalization using lapack" */ 
#include <stdio.h> 
#include <stdlib.h> 

/* DSYEV prototype */ 
extern void dsyev_(char* jobz, char* uplo, int* n, double* a, int* lda, 
       double* w, double* work, int* lwork, int* info); 
#define n 4  

int main(int argc, char *argv[]) 
{ 
    int i,j,info,lda,lwork,N; 
    double A[n][n], a[n*n], work[100*n],w[n]; 

    /* initialize matrices */ 
    for(i=0;i<n;i++) { for(j=0;j<n;j++) A[i][j] = (i+j); } 

    /* diagonalize */ 
    N=n; lda=n; lwork=10*n; info=0; 
    for(i=0;i<n;i++) { for(j=0;j<n;j++) a[i+j*n]=A[i][j]; } 
    dsyev_("V","L",&N,a,&lda,w,work,&lwork,&info); 

    /* print result */ 
    for(i=0;i<n;i++) { 
    printf("w[%d] = %8.4f | v[%d] = [ ",i,w[i],i); 
    for(j=0;j<n;j++) printf("%6.2f ",a[j+i*n]); 
    printf("]\n"); 
    } 

    return 0; 
} 

Оттуда я хотел бы пойти pdsyevd, который должен называться как:

SUBROUTINE PDSYEVD(JOBZ, UPLO, N, A, IA, JA, DESCA, W, Z, IZ, JZ, DESCZ, WORK, LWORK, IWORK, LIWORK, INFO) 

Ряд для меня все непонятно. Ответ на любой или несколько из этих вопросов будет высоко оценен.

  1. Есть ли у кого-нибудь пример?
  2. В документации ScaLAPACK говорится: «[...] PDSYEVD предполагает однородную систему [...], гетерогенная система может возвращать неверные результаты без сообщения об ошибке». Что это означает в этом контексте, «гомо-/гетерогенная» система?
  3. В конце документации говорится: «Распределенные подматрицы должны проверять некоторые свойства выравнивания, а именно [...]». Термины в этом выражении не входят даже во входные данные, как я могу узнать, удовлетворено ли это? MB_A/MB_Z?
  4. Как выбрать подматрицы для каждого процесса? Есть ли какое-либо обоснование? Я полагаю, что они должны быть более или менее равными по размеру, но строки/столбцы/квадраты/...? Может быть, больше для более редких регионов ...?
  5. Что делает Z/IZ/IJ/DESCZ во входном? Я уже даю каждому процессу подматрицу A/IA/JA/DESCA, над чем работать, так почему это Z? По-видимому, это частичная матрица собственного вектора, но почему это не написано в A, как в DSYEV?
  6. У всех процессов должен быть одинаковый размер блока? Может ли быть перекрытие подматриц или что я делаю для матриц простого размера, например?
  7. Что находится в DESCA? Кроме того, что такое DLEN? Кажется, это входной дескриптор массива для A. Я не уверен, что с этим делать.

Вот более или менее то, что я до сих пор, что не делает много:

/* "matrix diagonalization using scalapack" */ 
#include <mpi.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 

/* PDSYEVD prototype */ 
extern void pdsyevd_(char* jobz, char* uplo, int* n, double* a, int* ia, int* ja, int* desca, 
       double* w, double* z, int* iz, int* jz, int* descz, double* work, 
       int* lwork, double* iwork, int* liwork, int* info); 

#define n 4 

int main(int argc, char *argv[]) 
{ 
    int numprocs,myid,i,j,k,index,info,lwork,liwork,N; 
    int ia,ja,desca[n]; 
    int iz,jz,descz[n]; 
    double A[n][n],w[n]; 
    double *a,*z,*work,*iwork; 

    /* set up MPI stuff */ 
    MPI_Init(&argc,&argv);     // initialize MPI 
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs); // find out size of world 
    MPI_Comm_rank(MPI_COMM_WORLD,&myid);  // determine current mpi proc id 

    /* initialize matrices */ 
    for(i=0;i<n;i++) { for(j=0;j<n;j++) A[i][j] = (i+j); } 

    /* determine submatrices */ 

    /* let's use square blocks, of equal size: 
    there number of processors (mp^2) should be 
     - square (mp^2 = 1,2,4,9,16,..) 
     - with mp being a divisor of n 

    In case we have 4 procs and a 4x4 matrix for example 

     (A11 A12 A13 A14) 
     (A21 A22 A23 A24) 
    A = (A31 A32 A33 A34) 
     (A41 A42 A43 A44) 

     (a1 a2) 
     = (a3 a3) 

    where  (A11 A12) 
      a1 = (A21 A22) 

    is the submatrix sent to process 1 for example 

    in this case : 
     n=4 
     nprocs=4 --> mp=2 
     len = 2 
    */ 

    int mp = sqrt(numprocs); 
    if(numprocs!=mp*mp) {printf("ERROR: numprocs (%d) should be square.\n",numprocs); return 1; } 
    if(n%mp!=0) {printf("ERROR: mp (%d) should be divisor of n (%d).\n",mp,n); return 1; } 
    int len = n/mp; 
    a = malloc((n*n+1)*sizeof(double)); 
    z = malloc((n*n+1)*sizeof(double)); 
    //a = malloc((len*len+1)*sizeof(double)); 
    //z = malloc((len*len+1)*sizeof(double)); 

    ia=(myid*len)%n; // from 0 to n in steps of len 
    ja=(int)(myid/mp)*len; 
    printf("proc %d has a submatrix of size %d, with starting indices (%d,%d)\n",myid,len,ia,ja); 

    iz=ia; 
    jz=ja; 

    for(i=ia;i<ia+len;i++) { for(j=ja,k=0;j<ja+len;j++,k++) a[k]=A[i][j]; } 
    for(i=iz;i<iz+len;i++) { for(j=jz,k=0;j<jz+len;j++,k++) z[k]=A[i][j]; } 

    /* diagonalize */ 
    N=n; lwork=n*n; liwork=n*n; info=0; 
    work = malloc(lwork*sizeof(double)); 
    iwork = malloc(liwork*sizeof(double)); 

    for(i=0;i<n;i++) { for(j=0;j<n;j++) a[i+j*n]=A[i][j]; } 
    pdsyevd_("V","U",&len,a,&ia,&ja,desca,w,z,&iz,&jz,descz,work,&lwork,iwork,&liwork,&info); 
    if(!myid)printf("info = %d\n",info); 

    /* gather & print results */ 
    double wf[n]; 
    MPI_Reduce(w,wf,n,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); 
    if(myid==0) { 
    for(i=0;i<n;i++) { 
     printf("wf[%d] = %8.4f | v[%d] = [ ",i,wf[i],i); 
     for(j=0;j<n;j++) printf("%6.2f ",a[j+i*n]); 
     printf("]\n"); 
    } 
    } 

    free(a); free(z); free(work); free(iwork); 

    /* clean up */ 
    MPI_Finalize(); /* MPI Programs end with MPI Finalize; this is a weak synchronization point */ 
    return 0; 
} 
+0

ИМО этот вопрос будет лучше всего разделить на отдельные вопросы для отдельных частей. –

ответ

3

две полезные ссылки:

Я считаю, что поведение, описанное в документах IBM, соответствует ScaLAPACK, хотя и полностью документировано.

Для работы, работы, работы и т. Д .: set lwork = 0, и они должны быть назначены внутри подпрограммой по мере необходимости, не нужно передавать их.

Для z, iz, jz и т. Д .: если jobz = 'V', z содержит «обновленную локальную часть глобальной матрицы Z, где столбцы jz-jz + n-1 глобальной матрицы Z содержат ортонормированный собственные векторы глобальной матрицы A ". если jobz! = 'V', они не используются.

Более ответы на вопросы:

  1. Нет примеров, извините.
  2. Однородная система, как в http://en.wikipedia.org/wiki/System_of_linear_equations#Homogeneous_systems
  3. Извините, я не знаю, как ответить на это.
  4. Площади с примерно равным количеством ненулевых элементов. Примерно равные по размеру квадраты также, вероятно, хорошо.
  5. Использование Z описано выше и в документах, которые я связал. Я думаю, что это предусмотрено в качестве удобства для разработчиков.
  6. Нет, любой размер блока должен быть в порядке. Я догадываюсь разбить матрицу размера в две слегка неравные части.
  7. DESCA представляет собой массив из 9 целых чисел, содержащих различные размеры (глобальные строки/столбцы матрицы, блокировать строки/столбцы и т. Д.), Описанные в документах IBM.
+0

Поскольку никаких других ответов не появилось, и это отвечает хотя бы на некоторые из моих вопросов, это стоит щедрости, хотя это не отвечает на главный вопрос о том, как заставить его работать. Однако на самом деле я обнаружил, что есть примеры скальпаков, у меня есть рабочий код Fortran, основанный на этих примерах (опубликует его здесь). – jaap

Смежные вопросы