Я делаю простое нативное приложение MFC и использую пространство имен Concurrency для выполнения простой параллельной программы (рисования набора Мандельброта). Программа пока что очень простая, нажатие одной кнопки рисует параллельно, другая - последовательно. Функция последовательного выполнения очень проста и рисует правильную картину. Как и функция параллельного выполнения, однако при запуске отладочной сборки и выходе из программы вывод сообщает, что произошла утечка памяти.
Вот код:
void CMandelbrotView::DrawSetParallel() {
// Get client area dimension which will be the image size
RECT rect;
GetClientRect(&rect);
//GetClientRect(pDC, &rect);
int imageHeight(rect.bottom);
int imageWidth(rect.right);
const double realMin(-2.1); // Minimum real value
double imaginaryMin(-1.3); // Minimum imaginary value
double imaginaryMax(+1.3); // Maximum imaginary value
// Set maximum imaginary so axes are the same scale
double realMax(realMin+(imaginaryMax-imaginaryMin)*imageWidth/imageHeight);
// Get scale factors to convert pixel coordinates
double realScale((realMax-realMin)/(imageWidth-1));
double imaginaryScale((imaginaryMax-imaginaryMin)/(imageHeight-1));
CClientDC hdc(this); // DC is for this view
OnPrepareDC(&hdc); // Get origin adjusted
critical_section cs; // Mutex for BitBlt() operation
parallel_for(0, imageHeight, [&](int y) // Iterate parallel over image rows
{
cs.lock(); // Lock for access to client DC
// Create bitmap for one row of pixels in image
HDC memDC = CreateCompatibleDC(hdc); // Get device context to draw pixels
HBITMAP bmp = CreateCompatibleBitmap(hdc, imageWidth, 1);
cs.unlock(); // We are done with hdc here so unlock
HGDIOBJ oldBmp = SelectObject(memDC, bmp); // Select bitmap into DC
double cReal(0.0), cImaginary(0.0); // Stores c components
double zReal(0.0), zImaginary(0.0); // Stores z components
zImaginary = cImaginary = imaginaryMax - y*imaginaryScale;
for(int x = 0; x < imageWidth; x++) // Iterate over pixels in a row
{
zReal = cReal = realMin + x*realScale;
// Set current pixel color based on n
SetPixel(memDC, x, 0, Color(IteratePoint(zReal, zImaginary, cReal, cImaginary)));
}
cs.lock(); // Lock to write to hdc
// Transfer pixel row to client area device context
BitBlt(hdc, 0, y, imageWidth, 1, memDC, 0, 0, SRCCOPY);
cs.unlock(); // Release the lock
SelectObject(memDC, oldBmp);
DeleteObject(bmp); // Delete bmp
DeleteDC(memDC); // and our working DC
});}
Код для параллельного выполнения отличается от кода последовательного выполнения тем, что он создает отдельные строки образа Мандельброта параллельно и использует блокировку критической секции, чтобы убедиться, что потоки не борются за один и тот же дескриптор контекста устройства.
Теперь я сказал, что иногда сообщается об утечке памяти, потому что запуск релизной сборки не приводит к утечке памяти. Кроме того, при многократном запуске функции параллельного выполнения я не замечаю, что используется больше памяти, у меня 6 ГБ ОЗУ на случай, если кому-то интересно.
Что касается производительности, моя четырехъядерная машина на самом деле показывает примерно 4-кратное увеличение вычислений + скорость прорисовки при последовательном выполнении.
Я также видел похожие вопросы на веб-сайте msdn, но они не очень полезны, потому что это может быть ошибка VS. В любом случае, я бы хотел мнение параллельного программиста.