帮我看看这个二分法,通过线程池调用,为什么cpu就是飚不上去,笔记本最高50-60封顶了,2U的机架服务器才跑到20+就上不去了,主频还可低,二分法中的CCSMasses是一个长度为1000万的数组
if (dtSampleSource.Rows.Count > 0) {//有等待鉴定的数据 waitSampleCount = dtSampleSource.Rows.Count; foreach (DataRow item in dtSampleSource.Rows) { ThreadPool.QueueUserWorkItem(new WaitCallback(IDWithCompareFunction), item); } }
IDWithCompareFunction函数部分代码
//样本 DataRow sample = (DataRow)objSample; //样本峰 float[] masses = Array.ConvertAll<string, float>(sample["SampleMass"].ToString().Trim().Split('-'), s => float.Parse(s)); IEnumerable<float> result = masses.Where<float>(x => x <= (float)cAlgo.MassH & x >= (float)cAlgo.MassL); //根据参数限制过滤后的样本峰 float[] massesFilter = result.ToArray<float>(); //float[] signal = Array.ConvertAll<string, float>(sample["SampleSignalIntensity"].ToString().Trim().Split('-'), s => float.Parse(s)); #region 鉴定&比对结果数据源,区别在于MatchPer和Points,以匹配项为单位 DataTable dtIDMatchSource = new DataTable(); dtIDMatchSource.Columns.Add("ID", typeof(string)); dtIDMatchSource.Columns.Add("Tree_ID", typeof(string)); dtIDMatchSource.Columns.Add("Family", typeof(string)); dtIDMatchSource.Columns.Add("Genus", typeof(string)); dtIDMatchSource.Columns.Add("Species", typeof(string)); dtIDMatchSource.Columns.Add("Type", typeof(string)); dtIDMatchSource.Columns.Add("Mass", typeof(string)); dtIDMatchSource.Columns.Add("Signal", typeof(string)); dtIDMatchSource.Columns.Add("IdentFlag", typeof(int)); dtIDMatchSource.Columns.Add("Score", typeof(float)); dtIDMatchSource.Columns.Add("Matches", typeof(int)); dtIDMatchSource.Columns.Add("Points", typeof(int)); DataColumn[] cols = new DataColumn[] { dtIDMatchSource.Columns["ID"] }; dtIDMatchSource.PrimaryKey = cols; DataTable dtCompareMatchSource = dtIDMatchSource.Clone(); dtCompareMatchSource.Columns.Remove("Points"); dtCompareMatchSource.Columns.Add("MatchPer", typeof(float)); #endregion //鉴定,取参数设置的限制数量结果 dtIDMatchSource = IDFunction(dtIDMatchSource, massesFilter, 这是一个配置参数);
/// <summary> /// Mass二分法CCS比对 /// </summary> /// <param name="matchSource"></param> /// <param name="mass"></param> /// <param name="isUsed"></param> /// <param name="usePoint"></param> private void CCSMassMatch(ref DataTable matchSource, float mass,ref bool[] isUsed, Model.Identify.Algo cAlgo) { int LeftLocation = 0;//左边界 int RightLocation = 0;//右边界 int index = 0;//临时游标 int BetweenLocation = 0;//区间内游标 try { float NowMass = -1f;//当前游标对应的mass LeftLocation = 0; RightLocation = CCSPCount - 1; index = 0; BetweenLocation = -1; float error = Convert.ToSingle(cAlgo.Error); float MassL = mass - ((mass * error)); float MassH = mass + ((mass * error)); while ((RightLocation - LeftLocation) > 1)//当前游标位置小于总长度 { /* * while循环内,通过重设左右边界,缩小取值区间 */ index = ((RightLocation - LeftLocation) / 2) + LeftLocation;//临时游标位置 if ((index == RightLocation) | (index == LeftLocation))//当临时游标等于总长度或当前游标 { break; } NowMass = CCSMasses[index];//当前临时游标的mass值 if (NowMass > MassH)//当前mass比右边界大 { RightLocation = index;//设置右边界 } else { if (NowMass < MassL)//当前mass比左边界小 { LeftLocation = index;//设置左边界 continue; } if ((NowMass >= MassL) & (NowMass <= MassH)) { BetweenLocation = index;//处于匹配范围内的游标 break; } } } if (BetweenLocation >= 0) { while ((NowMass >= MassL) & (index > 0))//当前mass大于左区间,游标左移 { index--; NowMass = CCSMasses[index]; } while ((NowMass <= MassH) & (index < CCSPCount)) { if (((NowMass >= MassL) & (NowMass <= MassH)) & !isUsed[index])//当处于区间内并且未使用 { matchSource.Rows.Add(CCSIDS[index], NowMass.ToString(), CCSPoint[index]); } index++; NowMass = CCSMasses[index]; } } } catch (Exception) { throw; } }
dtSampleSource.Rows 太小,cpu多核没用上。
dtSampleSource.Rows 太大,都软中断去了。
随便瞎猜,不负责哦
dtSampleSource人为可控,10-1000都可以,就是每次从云服务器获取的需要处理的数据量,您认为多少合适
@MSky:
foreach (DataRow item in dtSampleSource.Rows)。不应该这样写。数据太少。并发没优势。数据太多,都是thread的上下文切换,效率不高。
可以这样,比如:dtSampleSource.Rows.asparallel().forall(doaction);用自带的并发库
@calvinK: 好的,了解一下,以前没这样用过