Re: Wielordzeniowosc - konkretne pytanie

Autor: Robert Winkler <winkel_at_NOSPAMpoczta.fm>
Data: Thu 26 Oct 2006 - 18:25:10 MET DST
Message-ID: <ehqnhs$jp6$1@atlantis.news.tpi.pl>
Content-Type: text/plain; format=flowed; charset="iso-8859-2"; reply-type=original

> [...]
> > Aby sporzystac z tej gigantycznej mocy obliczeniowej trzeba jednak pokonac dwa problemy
> > Pierwszym jest odnalezienie lub stworzenie wektorowego algorytmu
> > rozwiazujacego twój problem matematyczny.
> > Drugim jest odpowiednie zaprogramowanie jednostki vertexów znajdujacej sie w GPU
> > tak aby wykonal dla ciebie sposowne obliczenia.
> > Pierwszy problem musisz rozwiazac zamodzielnie
> > gdyz tylko ty znasz tematyke obliczen którymi bedziesz sie zajmowac.
> > Jesli chodzi o drugi, to muszisz odnalezc biblioteke
> > która pozwoli ci wydobyc moc kryjaca sie w GPU.
> [...]
>
> Koncepcja ciekawa, ale w praktyce nierealna. Czesc kodu, ktora ja
> zamierzam napisac jest duza objetosciowo, ale zajmuje malo czasu
> procesora. Czescia ktora bedzie najbardziej wymagajaca obliczeniowo
> jest procedurka diagonalizujaca duza ilosc sredniej wielkosci dosc
> wrednych zespolonych macierzy. A zeby taka PRZYZWOITA procedurke
> napisac samemu, to trzeba sie na tym znac, bo z tego co slyszalem, to
> zadanie nie jest calkiem trywialne. Mysle wiec, ze zebym ja prosty
> fizyko-chemik zaprogramowal efektywnie taka procedurke na GPU, to
> musialoby w Wisle tak duzo wody uplynac, ze sprawa jest po prostu
> nieoplacalna ;-)

Cały trik z biblioteka Accelerator polega własnie na tym
że prawie całkowicie odcina cię od wiedzy o sprzęcie
wykorzystywanym w czasie obliczeń.
Jedyna informacja jaką potrzebujesz to wiedza
o maksymalnym rozmiarze tekstur
które mogą być stosowane w twojej karcie graficznej.
Przykładowo moja karta graficzna obecnie to RADEON 9600
i dla niej maksymalna tekstura to 2048x2048
tak więc maksymalny rozmiar macierzy na
których moge wykonywać obliczenia
to własnie 2048 na 2048 licz zmiennoprzecinkowych
całkowitych, lub wartości boolean.

W aplikacji jedynym jawnym odwołaniej do grafiki jest wywołanie metody
ParallelArrays.InitGPU();

Znasz zapewne metode Monte Carlo
wyznaczania pzrybliżonej wartości liczby PI
(http://math.fullerton.edu/mathews/n2003/MonteCarloPiMod.html)

Oto jej implementacja wykorzystujaca biblioteke Accellerator:
<code lang="c#">
//(c) Microsoft Corporation. All rights reserved.
//
// Monnte Carlo pi aproximation
using System;
using Microsoft.Research.DataParallelArrays;
using PA = Microsoft.Research.DataParallelArrays.ParallelArrays;
public class MonteCarlo
{
  public static void Main()
  {
    // create randomly generated samples in the unit square centered on (0,0)
    int iSize = 1500;
    float[,] x = new float[iSize, iSize]; // x coordinate
    float[,] y = new float[iSize, iSize]; // y coordinate
    int i, j;

    // create an x and y arrays of random numbers between 0 and 1

    Random rnd = new Random();
    for (i = 0; i < iSize - 1; i++)
      for (j = 0; j < iSize - 1; j++)
      {
        x[i, j] = (float)rnd.NextDouble();
        y[i, j] = (float)rnd.NextDouble();
      }

    PA.InitGPU();

    // make x and y data parallel arrays
    DisposableFloatParallelArray parallelX = new DisposableFloatParallelArray(x);
    DisposableFloatParallelArray parallelY = new DisposableFloatParallelArray(y);

    // center them about (0, 0) with range (-1, 1)
    FloatParallelArray parallelXCentered;
    FloatParallelArray parallelYCentered;
    parallelXCentered = PA.Multiply(ParallelArrays.Subtract(parallelX, 0.5F), 2.0F);
    parallelYCentered = PA.Multiply(ParallelArrays.Subtract(parallelY, 0.5F), 2.0F);

    // calculate distance of (x,y) from 0, ie. Sqrt(x^2 + y^2)
    FloatParallelArray parallelXSquare;
    FloatParallelArray parallelYSquare;
    FloatParallelArray parallelDistance;
    parallelXSquare = PA.Multiply(parallelXCentered, parallelXCentered);
    parallelYSquare = PA.Multiply(parallelYCentered, parallelYCentered);
    parallelDistance = PA.Sqrt(PA.Add(parallelXSquare, parallelYSquare));
    float[,] test = new float[iSize, iSize];
    ParallelArrays.ToArray(parallelDistance, out test);

    // create an array of 1's if distance < 1, 0 if distance > 1
    FloatParallelArray parallelOne = new FloatParallelArray(1.0F, parallelX.Shape);
    FloatParallelArray parallelZero = new FloatParallelArray(0.0F, parallelX.Shape);
    FloatParallelArray parallelInCircle;
    parallelInCircle =
      PA.Select(PA.Subtract(parallelOne, parallelDistance), parallelOne, parallelZero);

    // the number inside the circle is the sum of the entire InCircle array
    FloatParallelArray parallelCountInCircle;
    parallelCountInCircle = PA.Sum(parallelInCircle);
    float[] inCircle = new float[1];
    PA.ToArray(parallelCountInCircle, out inCircle);
    parallelX.Dispose();
    parallelY.Dispose();

    // approximate pi--area of unit circle is pi
    // area of square from -1,1 is 4
    // inCircle/(total number of points) == pi/4
    float pi;
    pi = 4 * inCircle[0] / (iSize * iSize);
    System.Console.WriteLine("Pi is approximately " + pi.ToString());
    PA.UnInit();

    // Prompt user for exit
    Console.WriteLine("Press Enter to Exit");
    Console.ReadLine();
  }
}
</code>

Jak widzisz cały algorytm został sprowadzony
do kilku prostych operacji na macierzech.
Cały ciężar odpowiedniego przetłumaczenia tego na instrukcje GPU
został przerzucony na biblioteke uruchomieniową.
Tak wiec programist/fizyk/chemik wcale nie musi wiedzieć
że wszystkie jego obliczenia wykonuje jakiś procesor wektorowy
zaszyty w karcie graficznej.

-- 
____________
Robert Winkler 
Received on Thu Oct 26 18:30:06 2006

To archiwum zostało wygenerowane przez hypermail 2.1.8 : Thu 26 Oct 2006 - 18:51:25 MET DST