如何并行编程?
How to program this in parallel?
我目前遇到以下代码的性能问题。
private int globalType1 = 1;
private float globalType2 = 0.0342f;
private Dictionary<string, Tuple<int, float>> dt = new Dictionary<string, Tuple<int, float>>();
foreach (string file in Files) //assume 100 distinct files
{
//GetType1AndType2 is thread safe
Tuple<int, float> ift = GetType1AndType2(file, 0); //here 0 is the version of the file.
if (ift.Item1 == globalType1 && ift.Item2 == globalType2)
{
dt.Add(file + "_0", fftandFreq); //Key = <FileName_Version> ; Value = Tuple<Type1, Type2>
}
}
如何并行完成此操作。
您可以使用 Parallel.Foreach
:
Parallel.Foreach(Files, file =>
{
//GetType1AndType2 is thread safe
Tuple<int, float> ift = GetType1AndType2(file, 0); //here 0 is the version of the file.
if (ift.Item1 == globalType1 && ift.Item2 == globalType2)
{
lock (dt)
{
dt.Add(file + "_0", fftandFreq); //Key = <FileName_Version> ; Value = Tuple<Type1, Type2>
}
}
});
确保锁定您的字典或使用线程安全的字典类型。这是否有助于您的表现取决于内部采取的行动。如果它是基于 I/O 的,它可能没有那么大的好处,但你可以测试一下。
从技术上讲,它可以是这样的
private Dictionary<string, Tuple<int, float>> dt = Files
.AsParallel() // PLinq - parallel Linq
.Select(file => new {
ift = GetType1AndType2(file, 0),
file = file})
.Where(chunk => chunk.ift.Item1 == globalType1 &&
// Math.Abs(chunk.ift.Item2 - globalType2) < 0.00001
chunk.ift.Item2 == globalType2)
.ToDictionary(chunk => chunk.file + "_0",
chunk => chunk.ift); //TODO: check the value, please
但我怀疑性能问题是否真的出在这段代码中。 Files
(IO 操作通常 慢)是 性能[=35= 最可能的来源] 问题。
P.S. 比较 浮点数 值与 ==
操作 (Item2 == globalType2
) 是可疑,因为 舍入错误 (float globalType2 = 0.0342f;
很可能看起来是 0.0341999997
或 0.3420000002
)。如果您必须使用 float
类型(而不是 int
、string
等),请考虑与 tolerance 进行比较:更改 chunk.ift.Item2 == globalType2
到 Math.Abs(chunk.ift.Item2 - globalType2) < 0.00001
或类似的。
我目前遇到以下代码的性能问题。
private int globalType1 = 1;
private float globalType2 = 0.0342f;
private Dictionary<string, Tuple<int, float>> dt = new Dictionary<string, Tuple<int, float>>();
foreach (string file in Files) //assume 100 distinct files
{
//GetType1AndType2 is thread safe
Tuple<int, float> ift = GetType1AndType2(file, 0); //here 0 is the version of the file.
if (ift.Item1 == globalType1 && ift.Item2 == globalType2)
{
dt.Add(file + "_0", fftandFreq); //Key = <FileName_Version> ; Value = Tuple<Type1, Type2>
}
}
如何并行完成此操作。
您可以使用 Parallel.Foreach
:
Parallel.Foreach(Files, file =>
{
//GetType1AndType2 is thread safe
Tuple<int, float> ift = GetType1AndType2(file, 0); //here 0 is the version of the file.
if (ift.Item1 == globalType1 && ift.Item2 == globalType2)
{
lock (dt)
{
dt.Add(file + "_0", fftandFreq); //Key = <FileName_Version> ; Value = Tuple<Type1, Type2>
}
}
});
确保锁定您的字典或使用线程安全的字典类型。这是否有助于您的表现取决于内部采取的行动。如果它是基于 I/O 的,它可能没有那么大的好处,但你可以测试一下。
从技术上讲,它可以是这样的
private Dictionary<string, Tuple<int, float>> dt = Files
.AsParallel() // PLinq - parallel Linq
.Select(file => new {
ift = GetType1AndType2(file, 0),
file = file})
.Where(chunk => chunk.ift.Item1 == globalType1 &&
// Math.Abs(chunk.ift.Item2 - globalType2) < 0.00001
chunk.ift.Item2 == globalType2)
.ToDictionary(chunk => chunk.file + "_0",
chunk => chunk.ift); //TODO: check the value, please
但我怀疑性能问题是否真的出在这段代码中。 Files
(IO 操作通常 慢)是 性能[=35= 最可能的来源] 问题。
P.S. 比较 浮点数 值与 ==
操作 (Item2 == globalType2
) 是可疑,因为 舍入错误 (float globalType2 = 0.0342f;
很可能看起来是 0.0341999997
或 0.3420000002
)。如果您必须使用 float
类型(而不是 int
、string
等),请考虑与 tolerance 进行比较:更改 chunk.ift.Item2 == globalType2
到 Math.Abs(chunk.ift.Item2 - globalType2) < 0.00001
或类似的。