0

我有一个关于 CreateMutex() 的问题

我正在处理图像数据,并对图像的不同旋转进行某些计算。我以 180 步(1° 步)旋转图像,由于除了写回结果之外它们彼此独立,因此我决定进行这个多线程(非常密集的计算,并且写入内存占用了很多时间的执行)。

我最初尝试使用允许线程写入或不写入的单个互斥锁,但这大大降低了我的性能(从 100% 的单线程时间,没有互斥锁,到大约 80% 的执行速度)。

然后我创建了一个 HANDLE 数组,每个像素一个(因为它是 656x480,它大约有 300k 个句柄)。这将我的代码改进到大约 15% 的执行时间(同时 7 个线程)。

现在,当我在任务管理器中看到这个时,我看到它有自己的类别,称为 Handles,它在 30k(只有一些程序和操作系统运行)之间,在我的代码运行时达到 350k。

这种行为是好的,还是不好的,应该改变,如果是,为什么以及如何改变?

4

2 回答 2

3

我会说使用 350k+ 句柄的单个进程太多了。(每个像素一个句柄,真的吗?)

如果您希望使用多个线程来提高应用程序的整体效率,那么最好减少这些线程之间的争用量。我不太确定您的应用程序在做什么,但是如果您正在创建单个源图像的 180 次不同旋转,那么您可能会考虑制作源图像的 N 个副本(其中 N 是您要运行的线程数) ,并让每个线程在自己的源图像副本上工作。这样你就根本不需要互斥体了,你会减少线程之间的争用。

于 2012-07-30T23:07:56.627 回答
0

您应该使用CRITICAL_SECTION,而不是互斥锁。他们要快得多。如果使用 初始化,您可以获得类似自旋锁的行为InitializeCriticalSectionAndSpinCount()

就像其他人所说的那样,为每个像素设置一个互斥体是很疯狂的。你有多少线程?

您根本不需要任何锁定,您可以与 OpenMP 并行处理图像,而不是自己创建所有这些线程。OpenMP 的问题是,您可以有一个并行化的外部循环遍历输出图像的每一行,并在其中查看该行中的每个像素。现在你的输出是独立的。

要进行旋转,您需要从该输出像素的位置找到反向旋转的像素位置,然后对该位置的颜色值进行区域采样。这根本不应该是计算密集型的,特别是因为您只需为每个图像进行一次 sin 和 cos 计算(您的角度不会因每个像素而改变)。

所以,回顾一下……没有工作线程,没有互斥体,没有对 sin/cos 的冗余调用。您会惊讶于您的代码以多快的速度结束。

double sintheta = sin(theta);
double costheta = cos(theta);

#pragma omp parallel for 
for( int y = 0; y < height; y++ ) {
    RGB * inputRow = &inputImage[y * width];
    RGB * outputRow = &outputImage[y * width];

    for( int x = 0; x < width; x++ ) {
        // Whatever your rotation code should be.... =)
        double rotx = -((double)x - xCentre) * costheta;
        double roty = -((double)y - yCentre) * sintheta;

        // Interpolate colour from input image.  We've landed inside
        // a 2x2 square of pixels.  Take some of each.  I'll leave the
        // sampling to you...
        RGB val;
        // TODO

        // Output the rotated pixel without thread contention.
        outputRow[x] = val;
    }
}
于 2012-07-31T02:46:57.743 回答