программирование для нескольких ядер / Mandelbrot Set / c ++ - PullRequest
0 голосов
/ 16 декабря 2011

У меня есть вопрос, касающийся алгоритма Concurrency :: parallel_for заголовка "ppl.h".Этот пример взят из книги Айвор Хортон - «Начало Visual C ++ 2010».

Ссылка на полный файл .cpp: http://media.wiley.com/product_ancillary/83/04705008/DOWNLOAD/500880ch13.zip «Ch13 / Ex13_03 / Ex13_03.cpp»

Inв этом конкретном примере он показывает, как вы можете построить множество Мандельброта, используя параллельные вычисления.

Функция, которая его обрабатывает:

void DrawSetParallelFor(HWND hWnd)
{

// setting interface here
HDC hdc(GetDC(hWnd));
RECT rect;
GetClientRect(hWnd, & rect);

// getting width and height of our window
int imageHeight(rect.bottom);
int imageWidth(rect.right);

// defining variables and constants
const double realMin(-2.1); // Minimum real value
double imaginaryMin(-1.3); // Minimum imaginary value
double imaginaryMax(+1.3); // Maximum imaginary value
double realMax(realMin+(imaginaryMax-imaginaryMin)*imageWidth/imageHeight);
double realScale((realMax-realMin)/(imageWidth-1));
double imaginaryScale((imaginaryMax-imaginaryMin)/(imageHeight-1));

// defining critical section
Concurrency::critical_section cs; // Mutex for BitBlt() operation

// starting parallel loop
Concurrency::parallel_for(0, imageHeight, [&](int y)
{
   // locking code
   cs.lock();
      HDC memDC = CreateCompatibleDC(hdc);
      HBITMAP bmp = CreateCompatibleBitmap(hdc, imageWidth, 1);
   cs.unlock();

   HGDIOBJ oldBmp = SelectObject(memDC, bmp);

   double cReal(0.0), cImaginary(0.0);
   double zReal(0.0), zImaginary(0.0);

   zImaginary = cImaginary = imaginaryMax - y*imaginaryScale;

   // filling horizontal rows with colored pixels
   for(int x = 0; x < imageWidth; ++x)
   {
      zReal = cReal = realMin + x*realScale;
      SetPixel(memDC, x, 0, Color(IteratePoint(zReal, zImaginary, cReal, cImaginary)));
   }

   // locking again 
   cs.lock();
      BitBlt(hdc, 0, y, imageWidth, 1, memDC, 0, 0, SRCCOPY);
   cs.unlock();

   // deleting objects
   SelectObject(memDC, oldBmp);
   DeleteObject(bmp);
   DeleteDC(memDC);
});

   ReleaseDC(hWnd, hdc);
}

в основном эта функция отображает набор Мандельброта, который вычисляетсяв функции IteratePoint.

горизонтальные строки пикселей отображаются в случайном порядке.мой вопрос - как именно Concurrency::parallel_for алгоритм решает, какая область окна (т.е. набор "y" горизонтальных рядов пикселей) визуализируется каким ядром.

ps рабочий пример здесь: http://hotfile.com/dl/137661392/d63280a/MANDELBROT.rar.html

спасибо за потраченное время!

Ответы [ 2 ]

2 голосов
/ 16 декабря 2011

Похоже, parallel_for вызывает лямбда-функцию один раз с каждым значением от 0 до imageHeight.Фактически:

Concurrency::parallel_for(0, imageHeight, [&](int y) {

- это то же самое, что и:

for(int y=0; y<imageHeight; ++y) {

Таким образом, лямбда-функция вызывается один раз для каждого y в изображении, возможно, разделяя вызовы между несколькими рабочими потоками, чтобыони должны запускаться параллельно.

Поскольку parallel_for - это библиотечная функция, вам не стоит беспокоиться о том, как она работает внутри.Просто примите, что он вызывает лямду один раз для каждого y.Строго говоря, не существует определенного порядка, поскольку несколько вызовов могут происходить одновременно (например, на разных процессорных ядрах).

0 голосов
/ 16 декабря 2011

Это обрабатывается компилятором, когда потоки для каждого кода генерироваться. Компилятор отвечает за распространение инструкций для ядер.

Подробнее здесь:

http://www.multicoreinfo.com/research/papers/whitepapers/intel-opti-mc.pdf

http://arco.e.ac.upc.edu/wiki/images/b/b4/Madriles_isca09.pdf

...