C++中使用的HANDLE

HANDLE used in C++

本文关键字:HANDLE C++      更新时间:2023-10-16

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

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

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

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

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

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

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

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

您应该使用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;
    }
}