我对CreateMutex()
有疑问我正在处理图像数据,并针对图像的不同旋转进行某些计算。我以180步(1°步)旋转图像,并且由于除了将结果写回之外它们彼此独立,我决定进行这种多线程(非常密集的计算,并且写入内存就像没时间一样执行)。
我首先尝试使用一个允许线程写入或不写入的互斥锁,但这大大降低了我的性能(从单线程的100%时间,没有互斥,到执行速度的80%左右)。
然后我创建了一个HANDLE数组,每个像素一个(因为它的656x480,它的大约300k手柄)。这使我的代码增加到大约15%的执行时间(同时7个线程)。
现在,当我在任务管理器中看到它时,我发现它有自己的类别叫做Handles,它介于30k(只有一些程序和操作系统运行)之间,并且在我的代码运行时转到350k。
这种行为是正常的,还是不好,应该改变,如果是,为什么,以及如何改变?
答案 0 :(得分:3)
我会说使用350k +句柄的单个进程太多了。 (每个像素一个手柄,真的吗?)
如果您希望使用多个线程提高应用程序的整体效率,那么最好的办法是减少这些线程之间的争用量。我不太确定您的应用程序正在做什么,但如果您要创建180个不同的单个源图像轮换,那么您可以考虑制作源图像的N个副本(其中N是您要运行的线程数) ,让每个线程都在自己的源图像副本上工作。然后你根本不需要互斥锁,你将减少线程之间的争用。
答案 1 :(得分:0)
您应该使用CRITICAL_SECTION
,而不是互斥锁。它们要快得多。如果使用InitializeCriticalSectionAndSpinCount()
进行初始化,则可能会出现类似螺旋锁的行为。
您根本不需要任何锁定,您可以与OpenMP并行处理图像,而不是自己制作所有这些线程。使用OpenMP的是,您可以在输出图像的每一行上放置一个并行外部循环,并在其中查看该行中的每个像素。现在你的输出是独立的。
要进行旋转,您可以从该输出像素的位置找到反向旋转的像素位置,并对该位置的颜色值进行区域采样。这根本不应该是计算密集型的,特别是因为你只需要为每个图像进行一次正弦和余弦计算(你的角度不会因每个像素而改变)。
所以,回顾一下......没有工作线程,没有互斥体,没有多余的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;
}
}