我已经实现了一个简单函数的普通版本和并行版本,用于计算32bppArgb位图的直方图。正常版本在1920x1080像素的图像上大约需要0.03秒的时间,而并行版本则需要0.07秒。
线程开销真的那么大吗?除了Parallel.For之外,还有其他构造可以加速这个过程吗?我需要加快这个过程,因为我要处理每秒30帧的视频。
以下是简化版代码:
public sealed class Histogram
{
public int MaxA = 0;
public int MaxR = 0;
public int MaxG = 0;
public int MaxB = 0;
public int MaxT = 0;
public int [] A = null;
public int [] R = null;
public int [] G = null;
public int [] B = null;
public Histogram ()
{
this.A = new int [256];
this.R = new int [256];
this.G = new int [256];
this.B = new int [256];
this.Initialize();
}
public void Initialize ()
{
this.MaxA = 0;
this.MaxR = 0;
this.MaxG = 0;
this.MaxB = 0;
this.MaxT = 0;
for (int i = 0; i < this.A.Length; i++)
this.A [i] = 0;
for (int i = 0; i < this.R.Length; i++)
this.R [i] = 0;
for (int i = 0; i < this.G.Length; i++)
this.G [i] = 0;
for (int i = 0; i < this.B.Length; i++)
this.B [i] = 0;
}
public void ComputeHistogram (System.Drawing.Bitmap bitmap, bool parallel = false)
{
System.Drawing.Imaging.BitmapData data = null;
data = bitmap.LockBits
(
new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb
);
try
{
ComputeHistogram(data, parallel);
}
catch
{
bitmap.UnlockBits(data);
throw;
}
bitmap.UnlockBits(data);
}
public void ComputeHistogram (System.Drawing.Imaging.BitmapData data, bool parallel = false)
{
int stride = System.Math.Abs(data.Stride);
this.Initialize();
if (parallel)
{
unsafe
{
System.Threading.Tasks.Parallel.For
(
0,
data.Height,
new System.Threading.Tasks.ParallelOptions() { MaxDegreeOfParallelism = System.Environment.ProcessorCount },
y =>
{
byte* pointer = ((byte*) data.Scan0) + (stride * y);
for (int x = 0; x < stride; x += 4)
{
this.B [pointer [x + 0]]++;
this.G [pointer [x + 1]]++;
this.R [pointer [x + 2]]++;
this.A [pointer [x + 3]]++;
}
}
);
}
}
else
{
unsafe
{
for (int y = 0; y < data.Height; y++)
{
byte* pointer = ((byte*) data.Scan0) + (stride * y);
for (int x = 0; x < stride; x += 4)
{
this.B [pointer [x + 0]]++;
this.G [pointer [x + 1]]++;
this.R [pointer [x + 2]]++;
this.A [pointer [x + 3]]++;
}
}
}
}
for (int i = 0; i < this.A.Length; i++)
if (this.MaxA < this.A [i]) this.MaxA = this.A [i];
for (int i = 0; i < this.R.Length; i++)
if (this.MaxR < this.R [i]) this.MaxR = this.R [i];
for (int i = 0; i < this.G.Length; i++)
if (this.MaxG < this.G [i]) this.MaxG = this.G [i];
for (int i = 0; i < this.B.Length; i++)
if (this.MaxB < this.B [i]) this.MaxB = this.B [i];
if (this.MaxT < this.MaxA) this.MaxT = this.MaxA;
if (this.MaxT < this.MaxR) this.MaxT = this.MaxR;
if (this.MaxT < this.MaxG) this.MaxT = this.MaxG;
if (this.MaxT < this.MaxB) this.MaxT = this.MaxB;
}
}