![]() |
Инженерная методика адаптации приложения к гибридному кластеру с ускорителями на ПЛИСЧасть 2. Выбор модельного приложения.С. С. Андреев, С. А. Дбар, А. О. Лацис, Е. А. Плоткина
Модельное приложение выберем то же самое, что в «Десяти простых шагах». Приведем здесь несколько модифицированную выдержку из Шага 3: Выберем в качестве модельного приложения решение сеточного аналога двумерной задачи Дирихле для уравнения Пуассона на прямоугольной равномерной индексной сетке итерационным методом Якоби, без контроля невязки, то есть с заданием фиксированного числа итераций. Ниже приводится текст программы, реализующей этот расчет в последовательном режиме на универсальном процессоре. #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dimension.h"
// Change here the number of steps, the cell geometry, etc
#define NITER 5000
#define STEPITER 1000
#define delx 0.5
#define dely 0.25
// end change here.
int main( int argc, char **argv )
{
int i, j, n, mx1, my1, mx, my;
FILE *fp;
double rdx2, rdy2, beta;
/***/
if ( argc != 3 )
{
fprintf( stderr, "Usage: %s <nrows> <ncolumns>\n", argv[0] );
return (-1);
}
mx = (int)atol( argv[1] );
my = (int)atol( argv[2] );
mx += 2;
my += 2;
/* Here we know the array sizes, so make the arrays themselves: */
{
DIM2( double, f, my );
DIM2( double, newf, my );
DIM2( double, r, my );
void *tmpf;
/***/
f = (typeof(f))malloc( mx*sizeof(*f) );
newf = (typeof(newf))malloc( mx*sizeof(*f) );
r = (typeof(r))malloc( mx*sizeof(*r) );
if ( (!f) || (!newf) || (!r) )
{
fprintf( stderr, "Cannot allocate, exiting\n" );
return( -1 );
}
rdx2 = 1./delx/delx;
rdy2 = 1./dely/dely;
beta = 1.0/(2.0*(rdx2+rdy2));
printf( "Solving task on %d by %d grid\n", mx-2, my-2 );
fflush( stdout );
for ( i = 0; i < mx; i++ )
{
for ( j = 0; j < my; j++ )
{
if ( (i==0) || (j==0) || (i==(mx-1)) || (j==(my-1)) )
newf[i][j] = f[i][j] = 1.0;
else
newf[i][j] = f[i][j] = 0.0;
r[i][j] = 0.0;
}
}
mx1 = mx - 1;
my1 = my - 1;
/* Iteration loop: */
for ( n = 0; n < NITER; n++ )
{
if ( !(n%STEPITER) ) printf( "Iteration %d\n", n );
/* Step of calculation starts here: */
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;
}
}
/* swap the halves: */
tmpf = newf;
newf = f;
f = (typeof(f))tmpf;
}
fp = fopen("output_seq.dat", "w" );
for ( i = 1; i < (mx-1); i++ )
{
fwrite( &(f[i][1]), my-2, sizeof(f[0][0]), fp );
}
fclose( fp );
}
return 0;
}
Несколько кратких пояснений. Температура нормализована к диапазону от 0.0 до 1.0. Уравнение решается с правой частью, представленной массивом r, который в данном расчете заполняется нулями, но в пересчете значений температуры, тем не менее, участвует. Имеются два указателя, f и newf, которые указывают на два разных массива значений температуры, меняясь ролями на каждой итерации (если на текущей итерации f указывает на первый массив значений температуры, а newf – на второй, то на следующей итерации будет наоборот). При этом тот массив значений температуры, на которую на данной итерации указывает f, играет роль «старых» значений, а тот, на которую указывает newf, роль «новых». В остальном программа вполне тривиальна. Отныне она является для нас руководством к действию. Естественно, мы будем стремиться к параллельной, а затем — и гибридно-параллельной, реализации в точности тех вычислений, которые представлены приведенной выше последовательной программой. ◄ Часть 1 Часть 3 ► |
|
||||||||||||||||||||||||||||||||
| Тел. +7(499)220-79-72; E-mail: inform@kiam.ru | ||||||||||||||||||||||||||||||||||