![]() |
||||||||||||||||||||||||||||||||||
![]() |
||||||||||||||||||||||||||||||||||
![]()
|
RefNUMA – библиотека для организации виртуальной общей памяти в программах, использующих MPI.А. О. Лацис
Пример 10. То же модельное приложение на простых, не векторизованных разделяемых массивах, в гибридном варианте.Гибридный вариант главной программы рассмотренного в предыдущем разделе приложения приводится ниже. #include <mpi.h> #include <stdio.h> #include <stdlib.h> COARRAY_MEM_ALLOC( 2000000000l ); static void usage( void ) { printf( "Usage: progrev_coarr <nrows> <ncols> <niter>\n" ); exit( -1 ); } void itstep( int mx, int my, void *pf, void *pnewf, void *pr, double rdx2, double rdy2, double beta ); int main( int argc, char *argv[] ) { int mx, my, mx1, my1, niter, n_nodes, my_node; void *ra; long im, j, k; register int i; FILE *fp; double rdx2, rdy2, beta, t; #ifdef FORACCEL long accelstart, accelfinish, accelsize; #endif /***/ COARRAY_Init( &argc, &argv ); if ( argc != 4 ) usage(); rdx2 = 1.0; rdy2 = 1.0; beta = 0.25; my_node = coarray_my_node(); n_nodes = coarray_n_nodes(); mx = (int)atol( argv[1] ) + 2; my = (int)atol( argv[2] ) + 2; niter = (int)atol( argv[3] ); { typedef double element[my]; register long nblock; #ifdef FORACCEL void *af, *anewf, *ar; #endif nblock = shared_blocksize( (long)mx, n_nodes ); COARRAY_Create( element, fo, mx, 1.0 ); COARRAY_Create( element, newfo, mx, 1.0 ); COARRAY_Create( element, ro, mx, 1.0 ); #pragma refnuma shared f coarray fo blocksize nblock #pragma refnuma shared newf coarray newfo blocksize nblock #pragma refnuma shared r coarray ro blocksize nblock if ( (!fo) || (!newfo) || (!ro) ) { printf( "No memory\n" ); exit( -1 ); } #ifdef FORACCEL accelstart = SHARED_START( 1, mx ); accelfinish = SHARED_FINISH( mx-1, mx ); accelsize = accelfinish-accelstart; if ( accelsize <= 0 ) { accelsize = 0; } else { accelstart--; accelfinish++; accelsize += 2; } // printf( "Process %d: accelstart=%ld accelfinish=%ld accelsize=%ld\n", my_node, accelstart, accelfinish, accelsize ); if ( accelsize ) { af = calloc_accel( accelsize, my*sizeof(double) ); anewf = calloc_accel( accelsize, my*sizeof(double) ); ar = calloc_accel( accelsize, my*sizeof(double) ); if ( (!af) || (!anewf) || (!ar) ) { printf( "No device memory\n" ); exit( -1 ); } } #endif /***/ #pragma refnuma parallel for arraysize mx for ( i = 0; i < mx; i++ ) { for ( j = 0; j < my; j++ ) { f[i][j] = newf[i][j] = 0.0; r[i][j] = 0.0; if ( (i == 0) || (i == (mx-1)) || (j == 0) || (j == (my-1)) ) f[i][j] = newf[i][j] = 1.0; } } #ifdef FORACCEL shared_to_accel( af, (void **)f, mx, accelstart, accelsize, my*sizeof(double), REALLYCOPY ); shared_to_accel( anewf, (void **)newf, mx, accelstart, accelsize, my*sizeof(double), REALLYCOPY ); shared_to_accel( ar, (void **)r, mx, accelstart, accelsize, my*sizeof(double), REALLYCOPY ); #endif coarray_barrier(); t = MPI_Wtime(); for ( k = 0; k < niter; k++ ) { #ifdef FORACCEL if ( accelsize ) { shared_to_accel( af, (void **)f, mx, accelstart, accelsize, my*sizeof(double), JUSTUPDATE ); itstep( accelsize, my, af, anewf, ar, rdx2, rdy2, beta ); shared_from_accel( (void **)newf, mx, accelstart, anewf, accelsize, my*sizeof(double), JUSTUPDATE ); } #else itstep( mx, my, f, newf, r, rdx2, rdy2, beta ); #endif coarray_barrier(); ra = (void*)f; f = newf; newf = (typeof(newf))ra; #ifdef FORACCEL ra = (void*)af; af = anewf; anewf = (typeof(anewf))ra; #endif } t = MPI_Wtime() - t; printf( "Time: %f speed %f flops\n", t, (((double)(mx-2))*((double)(my-2))*7.0*niter)/t ); #ifdef FORACCEL shared_from_accel( (void **)f, mx, accelstart+1, ((double*)af)+my, accelsize-2, my*sizeof(double), REALLYCOPY ); #endif if ( !my_node ) { fp = fopen( "progrev_coarr.dat", "w" ); fclose( fp ); } NODE_BY_NODE_BEGIN( k, 0, n_nodes ) fp = fopen( "progrev_coarr.dat", "a" ); #pragma refnuma parallel for arraysize mx for ( i = 1; i < (mx-1); i++ ) { fwrite( f[i]+1, sizeof(double), my-2, fp ); // for ( j = 1; j < my1; j++ ) fprintf( fp, "%f ", f[i][j] ); fprintf( fp, "\n" ); } fclose( fp ); coarray_report( (void**)f, &im, &j ); printf( "In node %d for f: requested %ld used %ld\n", my_node, im, j ); coarray_report( (void**)newf, &im, &j ); printf( "In node %d for newf: requested %ld used %ld\n", my_node, im, j ); coarray_report( (void**)r, &im, &j ); printf( "In node %d for r: requested %ld used %ld\n", my_node, im, j ); fflush( stdout ); NODE_BY_NODE_END #pragma refnuma shared f off #pragma refnuma shared newf off #pragma refnuma shared r off } COARRAY_Finalize(); return 0; } #ifndef FORACCEL void itstep( int mx, int my, void *pf, void *pnewf, void *pr, double rdx2, double rdy2, double beta ) { int mx1, my1; register int i, j; /***/ typedef double element[my]; register long nblock; nblock = shared_blocksize( (long)mx, coarray_n_nodes() ); COARRAY_Create_from_arg( element, fo, pf ); COARRAY_Create_from_arg( element, newfo, pnewf ); COARRAY_Create_from_arg( element, ro, pr ); #pragma refnuma shared f coarray fo blocksize nblock #pragma refnuma shared newf coarray newfo blocksize nblock #pragma refnuma shared r coarray ro blocksize nblock mx1 = mx - 1; my1 = my - 1; #pragma refnuma parallel for arraysize mx for ( i = 1; i < mx1; i++ ) { for ( j = 1; j < my1; j++ ) { newf[i][j] = ((f[i-1][j]+f[i+1][j])*rdx2+(f[i][j-1]+f[i][j+1])*rdy2-r[i][j])*beta; } } #pragma refnuma shared f off #pragma refnuma shared newf off #pragma refnuma shared r off } #endif По сравнению с рассмотренными ранее примерами, в этом тексте интерес представляют впервые появившиеся функции shared_to_accel() и shared_from_accel(). Это стандартные функции копирования данных между процессорной и сопроцессорной памятью, очень похожие на уже рассмотренные выше функции vectorized_to_accel() и vectorized_from_accel(). Отличие состоит в отсутствии аргумента, задающего длину строки массива общей памяти. При использовании этих функций следует обратить внимание на правильность задания значения аргумента «длина элемента массива в байтах». Для функций vectorized…() под элементом понимался элемент двумерного массива, то есть, в нашем примере, элемент имееет тип double, размер элемента равен sizeof(double). Для функций shared…() под элементом понимается элемент одномерного массива, то есть, в нашем примере, элемент имеет тип element, размер элемента равен sizeof(element), или, что есть то же самое, my*sizeof(double). ◄ Пример 9 Приложение 1 ► |
![]() |
||||||||||||||||||||||||||||||||
Тел. +7(499)220-79-72; E-mail: inform@kiam.ru |