저는 간단한 네이티브 MFC 응용 프로그램을 만들고 있고, 동시성 네임 스페이스를 사용하여 간단한 병렬 프로그램 (Mandelbrot 집합 그리기)을 수행하고 있습니다. 이 프로그램은 지금까지 아주 기본적으로 하나의 버튼을 클릭하면 병렬로 그려지고, 다른 하나는 직렬로 그려집니다. 직렬 실행 기능은 매우 기본적이고 올바른 그림을 그립니다. 그러나 병렬 실행 기능과 마찬가지로 디버그 빌드를 실행하고 프로그램을 종료 할 때 출력에서 메모리 누수가 있음을 알 수 있습니다. 여기 parallel_for 함수로 인해 메모리 누수가 발생합니다. (가끔)
코드이다 :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
});}
병렬 실행을위한 코드가 병렬 만델 화상의 별도의 열을 생성하는 일련의 실행 코드와 다르고, 쓰레드 확인 크리티컬 섹션 잠금 사용 같은 장치 컨텍스트 핸들을 통해 싸우지 마십시오.
이제 메모리 누수가보고 된 이유는 릴리스 빌드를 실행해도 메모리 누수가보고되지 않기 때문입니다. 또한, 병렬 실행 기능을 여러 번 실행하면 더 많은 메모리가 소모되는 것을 실제로 인식하지 못합니다. 누군가가 궁금해하는 경우 6GB의 RAM이 있습니다. 성능면에서 볼 때, 제 쿼드 코어 머신은 실제로 직렬 실행에서 계산 + 드로잉 속도가 대략 4 배 증가했습니다. msvn 웹 사이트에서도 이와 유사한 질문을하지만 VS 버그 일 수 있기 때문에 많이 사용하지는 않습니다. 어쨌든, 필자는 병렬 프로그래머의 의견을 원합니다.
누수가 예상되는 곳을 좁히려 고 시도해 보셨습니까? GDI 코드 (GDI 리소스 누출은 거의 메모리 누수로보고되지 않음)에서 비롯된 것이 아니므로 모든 것을 제거하고 IteratePoint 루프를 병렬로 호출하면됩니다. 그래도 여전히 누출되면, 무엇을하는지보십시오 (제공된 코드 샘플에서는 볼 수 없습니다). –
@Leo 사실, parallel_for 함수에서 모든 것을 제거했는데, parallel_for 문을 사용하면 디버그 빌드를 실행할 때 메모리 누수가 발생하는 것 같습니다. VS10 설치시 컴파일러, 디버거 또는 작은 결함 일 수 있습니다. 나는 아직도 약간의 설명을 원할 것이다. – sj755
관련없는 코드를 모두 제거하려면 질문을 편집해야합니다. 그런 식으로 사람들은 무엇이 잘못 될지를 볼 수있게 될 것입니다. 또한 단지 잘못보고 된 것이 아니라고 확신합니까? 메모리 누수 도구는 가양성에 대해 악명이 높습니다. 어느 도구가이를보고하고 있으며 정확하게보고하고 있습니까? –