我的电脑有:24核,32 GB RAM
我已经知道了一段时间并且读到有关使用Parallel.ForEach
执行繁重任务时可以在计算机中使用更多/所有核心的可能性
但我完全不明白如何做到这一点。我将抓住机会给出我的实时示例,该示例使用我现在使用的包含以下代码的单个循环。
现在需要57秒来执行代码。
在这个循环中有超过300万次循环/计算。
只是给出这个循环是不可能从我粘贴的代码测试,因为没有记忆输入到该函数。
是否有一个解决方案如何使用与我的计算机一样多的内核来执行此代码? (我的电脑里有24个核心)
代码返回这两个列表:
List<String> minusLIST
List<String> plusLIST
public void calculationFunction(Dictionary<String, List<String>> tr1, Dictionary<String, List<ArrayList>> v1, Dictionary<String, bool> v5,
Dictionary<String, int> infoIndex, out List<String> minusLIST, out List<String> plusLIST)
{
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
double num1 = 0; double num2 = 0; double num3 = 0; double number1 = 0; double number2 = 0; double number3 = 0; double thenum1 = 0; double thenum2 = 0; double thenum3 = 0;
double NUM1 = 0; double NUM2 = 0; double NUM3 = 0; double NUMBER1 = 0; double NUMBER2 = 0; double NUMBER3 = 0; String str = ""; String num11 = ""; String num22 = ""; String num33 = "";
String number11 = ""; String number22 = ""; String number33 = ""; double calc1 = 0;
minusLIST = new List<String>(); plusLIST = new List<String>();
foreach (KeyValuePair<String, List<String>> entry in tr1)
{
List<String> allparams = new List<String>(entry.Value);
if (allparams.Count == 10)
{
if (v5.ContainsKey(allparams[7]) && v5.ContainsKey(allparams[8]) && v5.ContainsKey(allparams[9]))
{
if (v5[allparams[7]] && v5[allparams[8]] && v5[allparams[9]])
{
//Calculate both calc scenarios!
num1 = (double)v1[allparams[0]][infoIndex[allparams[7]]][0]; number1 = (double)v1[allparams[0]][infoIndex[allparams[7]]][1]; thenum1 = (double)v1[allparams[0]][infoIndex[allparams[7]]][2];
num2 = (double)v1[allparams[1]][infoIndex[allparams[8]]][0]; number2 = (double)v1[allparams[1]][infoIndex[allparams[8]]][1]; thenum2 = (double)v1[allparams[1]][infoIndex[allparams[8]]][2];
num3 = (double)v1[allparams[2]][infoIndex[allparams[9]]][0]; number3 = (double)v1[allparams[2]][infoIndex[allparams[9]]][1]; thenum3 = (double)v1[allparams[2]][infoIndex[allparams[9]]][2];
NUM1 = num1; NUM2 = num2; NUM3 = num3; NUMBER1 = number1; NUMBER2 = number2; NUMBER3 = number3;
if (num1 <= 0 || number1 <= 0) { NUM1 = thenum1; NUMBER1 = thenum1; }
if (num2 <= 0 || number2 <= 0) { NUM2 = thenum2; NUMBER2 = thenum2; }
if (num3 <= 0 || number3 <= 0) { NUM3 = thenum3; NUMBER3 = thenum3; }
if (NUM1 > 0 && NUM2 > 0 && NUM3 > 0 && NUMBER1 > 0 && NUMBER2 > 0 && NUMBER3 > 0)
{
str = ""; num11 = ""; num22 = ""; num33 = ""; number11 = ""; number22 = ""; number33 = "";
if (num1 > 0 && num2 > 0 && num3 > 0 && number1 > 0 && number2 > 0 && number3 > 0) { } else { str = string.Format("{0:F10}", thenum1) + " / " + string.Format("{0:F10}", thenum2) + " / " + string.Format("{0:F10}", thenum3); }
if (num1 <= 0) { num11 = "0"; num1 = thenum1; } else { num11 = string.Format("{0:F10}", num1); }
if (num2 <= 0) { num22 = "0"; num2 = thenum2; } else { num22 = string.Format("{0:F10}", num2); }
if (num3 <= 0) { num33 = "0"; num3 = thenum3; } else { num33 = string.Format("{0:F10}", num3); }
if (number1 <= 0) { number11 = "0"; number1 = thenum1; } else { number11 = string.Format("{0:F10}", number1); }
if (number2 <= 0) { number22 = "0"; number2 = thenum2; } else { number22 = string.Format("{0:F10}", number2); }
if (number3 <= 0) { number33 = "0"; number3 = thenum3; } else { number33 = string.Format("{0:F10}", number3); }
//Calculate
if (allparams[6] == "0")
{
calc1 = ((num1 * number2 * number3) - 45) / 10;
}
else
{
calc1 = (((num1 * number2) / number3) + 45) / 10;
}
//String
str = calc1 + "," + allparams[0] + " - " + allparams[1] + " - " + allparams[2] + "," +
allparams[3] + " - " + allparams[4] + " - " + allparams[5] + "," +
num11 + " / " + num22 + " / " + num33 + "," +
number11 + " / " + number22 + " / " + number33 + "," +
str + "," +
calc1 + "%";
if (calc1 > 0) { plusLIST.Add(str); }
else
{
minusLIST.Add(str);
}
}
}
}
}
}
}
我确实在代码中放了Parallel.ForEach循环。我也注意到我“不得不??”放一个锁对象,因为下面的列表似乎完全弄乱了,因为它与其他线程共享变量。
if (calc1 > 0) { plusLIST2.Add(str); }
else
{
minusLIST2.Add(str);
}
看来Parallel.ForEach不是线程安全的吗?
当这个代码运行时,单个循环需要62秒-vs- 57秒。
如果用24芯不能更快地做到这一点吗?我知道锁对象也会阻塞代码,这也是代码自由运行的“瓶颈”?
public void calculationFunction(Dictionary<String, List<String>> tr1, Dictionary<String, List<ArrayList>> v1, Dictionary<String, bool> v5,
Dictionary<String, int> infoIndex, out List<String> minusLIST, out List<String> plusLIST)
{
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
double num1 = 0; double num2 = 0; double num3 = 0; double number1 = 0; double number2 = 0; double number3 = 0; double thenum1 = 0; double thenum2 = 0; double thenum3 = 0;
double NUM1 = 0; double NUM2 = 0; double NUM3 = 0; double NUMBER1 = 0; double NUMBER2 = 0; double NUMBER3 = 0; String str = ""; String num11 = ""; String num22 = ""; String num33 = "";
String number11 = ""; String number22 = ""; String number33 = ""; double calc1 = 0;
minusLIST = new List<String>(); plusLIST = new List<String>();
List<String> minusLIST2 = new List<String>(); List<String> plusLIST2 = new List<String>(); object lockobj = new object();
Parallel.ForEach(tr1, entry =>
{
List<String> allparams = new List<String>(entry.Value);
if (allparams.Count == 10)
{
if (v5.ContainsKey(allparams[7]) && v5.ContainsKey(allparams[8]) && v5.ContainsKey(allparams[9]))
{
if (v5[allparams[7]] && v5[allparams[8]] && v5[allparams[9]])
{
//Calculate both calc scenarios!
num1 = (double)v1[allparams[0]][infoIndex[allparams[7]]][0]; number1 = (double)v1[allparams[0]][infoIndex[allparams[7]]][1]; thenum1 = (double)v1[allparams[0]][infoIndex[allparams[7]]][2];
num2 = (double)v1[allparams[1]][infoIndex[allparams[8]]][0]; number2 = (double)v1[allparams[1]][infoIndex[allparams[8]]][1]; thenum2 = (double)v1[allparams[1]][infoIndex[allparams[8]]][2];
num3 = (double)v1[allparams[2]][infoIndex[allparams[9]]][0]; number3 = (double)v1[allparams[2]][infoIndex[allparams[9]]][1]; thenum3 = (double)v1[allparams[2]][infoIndex[allparams[9]]][2];
NUM1 = num1; NUM2 = num2; NUM3 = num3; NUMBER1 = number1; NUMBER2 = number2; NUMBER3 = number3;
if (num1 <= 0 || number1 <= 0) { NUM1 = thenum1; NUMBER1 = thenum1; }
if (num2 <= 0 || number2 <= 0) { NUM2 = thenum2; NUMBER2 = thenum2; }
if (num3 <= 0 || number3 <= 0) { NUM3 = thenum3; NUMBER3 = thenum3; }
if (NUM1 > 0 && NUM2 > 0 && NUM3 > 0 && NUMBER1 > 0 && NUMBER2 > 0 && NUMBER3 > 0)
{
lock (lockobj)
{
str = ""; num11 = ""; num22 = ""; num33 = ""; number11 = ""; number22 = ""; number33 = "";
if (num1 > 0 && num2 > 0 && num3 > 0 && number1 > 0 && number2 > 0 && number3 > 0) { } else { str = string.Format("{0:F10}", thenum1) + " / " + string.Format("{0:F10}", thenum2) + " / " + string.Format("{0:F10}", thenum3); }
if (num1 <= 0) { num11 = "0"; num1 = thenum1; } else { num11 = string.Format("{0:F10}", num1); }
if (num2 <= 0) { num22 = "0"; num2 = thenum2; } else { num22 = string.Format("{0:F10}", num2); }
if (num3 <= 0) { num33 = "0"; num3 = thenum3; } else { num33 = string.Format("{0:F10}", num3); }
if (number1 <= 0) { number11 = "0"; number1 = thenum1; } else { number11 = string.Format("{0:F10}", number1); }
if (number2 <= 0) { number22 = "0"; number2 = thenum2; } else { number22 = string.Format("{0:F10}", number2); }
if (number3 <= 0) { number33 = "0"; number3 = thenum3; } else { number33 = string.Format("{0:F10}", number3); }
//Calculate
if (allparams[6] == "0")
{
calc1 = ((num1 * number2 * number3) - 45) / 10;
}
else
{
calc1 = (((num1 * number2) / number3) + 45) / 10;
}
//String
str = calc1 + "," + allparams[0] + " - " + allparams[1] + " - " + allparams[2] + "," +
allparams[3] + " - " + allparams[4] + " - " + allparams[5] + "," +
num11 + " / " + num22 + " / " + num33 + "," +
number11 + " / " + number22 + " / " + number33 + "," +
str + "," +
calc1 + "%";
if (calc1 > 0) { plusLIST2.Add(str); }
else
{
minusLIST2.Add(str);
}
}
}
}
}
}
});
plusLIST = new List<String>(plusLIST2);
minusLIST = new List<String>(minusLIST2);
}
我成功地运行了以下代码:“Parallel.ForEach(tr1,entry =>”循环。当我在循环中声明所有变量时。变量现在没有在线程中混淆。我还需要放.Add到2个列表时的锁定对象。
现在需要12秒(Parallel.ForEach)-VS- 57秒(单循环)所以这是一个4.75倍的改进。
但是,我确实有24个内核,所以我想知道为什么它不会以例如至少快15-20倍的速度?
为了尽可能多地使用/所有核心,我该怎么办?
public void calculationFunction(Dictionary<String, List<String>> tr1, Dictionary<String, List<ArrayList>> v1, Dictionary<String, bool> v5,
Dictionary<String, int> infoIndex, out List<String> minusLIST, out List<String> plusLIST)
{
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
minusLIST = new List<String>(); plusLIST = new List<String>();
List<String> minusLIST2 = new List<String>(); List<String> plusLIST2 = new List<String>(); object lockobj = new object();
Parallel.ForEach(tr1, entry =>
{
List<String> allparams = new List<String>(entry.Value);
if (allparams.Count == 10)
{
if (v5.ContainsKey(allparams[7]) && v5.ContainsKey(allparams[8]) && v5.ContainsKey(allparams[9]))
{
if (v5[allparams[7]] && v5[allparams[8]] && v5[allparams[9]])
{
double num1 = 0; double num2 = 0; double num3 = 0; double number1 = 0; double number2 = 0; double number3 = 0; double thenum1 = 0; double thenum2 = 0; double thenum3 = 0;
double NUM1 = 0; double NUM2 = 0; double NUM3 = 0; double NUMBER1 = 0; double NUMBER2 = 0; double NUMBER3 = 0; String str = ""; String num11 = ""; String num22 = ""; String num33 = "";
String number11 = ""; String number22 = ""; String number33 = ""; double calc1 = 0;
//Calculate both calc scenarios!
num1 = (double)v1[allparams[0]][infoIndex[allparams[7]]][0]; number1 = (double)v1[allparams[0]][infoIndex[allparams[7]]][1]; thenum1 = (double)v1[allparams[0]][infoIndex[allparams[7]]][2];
num2 = (double)v1[allparams[1]][infoIndex[allparams[8]]][0]; number2 = (double)v1[allparams[1]][infoIndex[allparams[8]]][1]; thenum2 = (double)v1[allparams[1]][infoIndex[allparams[8]]][2];
num3 = (double)v1[allparams[2]][infoIndex[allparams[9]]][0]; number3 = (double)v1[allparams[2]][infoIndex[allparams[9]]][1]; thenum3 = (double)v1[allparams[2]][infoIndex[allparams[9]]][2];
NUM1 = num1; NUM2 = num2; NUM3 = num3; NUMBER1 = number1; NUMBER2 = number2; NUMBER3 = number3;
if (num1 <= 0 || number1 <= 0) { NUM1 = thenum1; NUMBER1 = thenum1; }
if (num2 <= 0 || number2 <= 0) { NUM2 = thenum2; NUMBER2 = thenum2; }
if (num3 <= 0 || number3 <= 0) { NUM3 = thenum3; NUMBER3 = thenum3; }
if (NUM1 > 0 && NUM2 > 0 && NUM3 > 0 && NUMBER1 > 0 && NUMBER2 > 0 && NUMBER3 > 0)
{
str = ""; num11 = ""; num22 = ""; num33 = ""; number11 = ""; number22 = ""; number33 = "";
if (num1 > 0 && num2 > 0 && num3 > 0 && number1 > 0 && number2 > 0 && number3 > 0) { } else { str = string.Format("{0:F10}", thenum1) + " / " + string.Format("{0:F10}", thenum2) + " / " + string.Format("{0:F10}", thenum3); }
if (num1 <= 0) { num11 = "0"; num1 = thenum1; } else { num11 = string.Format("{0:F10}", num1); }
if (num2 <= 0) { num22 = "0"; num2 = thenum2; } else { num22 = string.Format("{0:F10}", num2); }
if (num3 <= 0) { num33 = "0"; num3 = thenum3; } else { num33 = string.Format("{0:F10}", num3); }
if (number1 <= 0) { number11 = "0"; number1 = thenum1; } else { number11 = string.Format("{0:F10}", number1); }
if (number2 <= 0) { number22 = "0"; number2 = thenum2; } else { number22 = string.Format("{0:F10}", number2); }
if (number3 <= 0) { number33 = "0"; number3 = thenum3; } else { number33 = string.Format("{0:F10}", number3); }
//Calculate
if (allparams[6] == "0")
{
calc1 = ((num1 * number2 * number3) - 45) / 10;
}
else
{
calc1 = (((num1 * number2) / number3) + 45) / 10;
}
//String
str = calc1 + "," + allparams[0] + " - " + allparams[1] + " - " + allparams[2] + "," +
allparams[3] + " - " + allparams[4] + " - " + allparams[5] + "," +
num11 + " / " + num22 + " / " + num33 + "," +
number11 + " / " + number22 + " / " + number33 + "," +
str + "," +
calc1 + "%";
if (calc1 > 0)
{
lock (lockobj) { plusLIST2.Add(str); }
}
else
{
lock (lockobj) { minusLIST2.Add(str); }
}
}
}
}
}
});
plusLIST = new List<String>(plusLIST2);
minusLIST = new List<String>(minusLIST2);
}