首页 新闻 会员 周边 捐助

通过线程池调用这个函数,为什么cpu使用率上不去【c#】

0
[已解决问题] 解决于 2016-11-19 14:49

帮我看看这个二分法,通过线程池调用,为什么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;
            }
        }
复制代码
MSky的主页 MSky | 菜鸟二级 | 园豆:436
提问于:2016-11-18 21:52
< >
分享
最佳答案
0

dtSampleSource.Rows 太小,cpu多核没用上。

dtSampleSource.Rows 太大,都软中断去了。

随便瞎猜,不负责哦

奖励园豆:5
czd890 | 专家六级 |园豆:14488 | 2016-11-19 00:01

dtSampleSource人为可控,10-1000都可以,就是每次从云服务器获取的需要处理的数据量,您认为多少合适

MSky | 园豆:436 (菜鸟二级) | 2016-11-19 09:39

@MSky: 

foreach (DataRow item in dtSampleSource.Rows)。不应该这样写。数据太少。并发没优势。数据太多,都是thread的上下文切换,效率不高。

可以这样,比如:dtSampleSource.Rows.asparallel().forall(doaction);用自带的并发库

czd890 | 园豆:14488 (专家六级) | 2016-11-19 21:59

@calvinK: 好的,了解一下,以前没这样用过

MSky | 园豆:436 (菜鸟二级) | 2016-11-20 13:17
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册