多线程的多核分配问题验证

using System.Diagnostics;
using System;
using System.Threading.Tasks;

namespace THREADS
{
    class Threads
    {
        public double[] times = new double[4];
        public int[] counts = new int[] { 40000000, 50000000, 70000000 };

        /***
         * 测试验证
         * 1,当一个进程有多个线程时,操作系统会自动将线程分配到不同的CPU上,最优化分配
         */
        public void Start()
        {
            var sw = new Stopwatch();
            var tasks = new Task[4];

            /***
             * Step1,创建四个线程,(使用 new Thread是等效的)
             */

            //测试1,三个线程,每个线程跑一个任务
            tasks[0] = new Task(() => {
                DoTask(counts[0]);
                times[0] = sw.ElapsedMilliseconds;
            });
            tasks[1] = new Task(() => {
                DoTask(counts[1]);
                times[1] = sw.ElapsedMilliseconds;
            });
            tasks[2] = new Task(() => {
                DoTask(counts[2]);
                times[2] = sw.ElapsedMilliseconds;
            });

            //测试2,一个线程跑三个任务
            tasks[3] = new Task(() => {
                DoTask(counts[0]);
                DoTask(counts[1]);
                DoTask(counts[2]);
                times[3] = sw.ElapsedMilliseconds;
            });

            /***
             * Step2,开启测试线程
             */
            //PrintProcessInfo("测试线程开启前"); 开启会使t4时间反而变短了,原因不明
            //BindThreadToCpu(0); 在此位置绑定是无效的,因为我们的测试线程还没开启,无法将它们都绑定到某个核上

            sw.Start();
            tasks[0].Start();
            tasks[1].Start();
            tasks[2].Start();
            tasks[3].Start();

            /***
             * Step3,绑定所有线程到某个核上
             * 可以发现,绑定后所有线程的运算时间都明显加长了,因为它们共用一个CPU(debug模式效果更明显,release模式在数据量小时不明显)
             */
            long bindtime = 0;
            if (true)
            {
                var tsw = Stopwatch.StartNew();
                var t0 = tsw.ElapsedMilliseconds;
                BindThreadToCpu(0); //在此位置绑定是有效的,因为我们的测试线程已经开启,可以将它们都绑定到某个核上
                bindtime = tsw.ElapsedMilliseconds - t0;
            }

            /***
             * Step4,等待所有线程结束打印运行时间
             */
            //PrintProcessInfo("测试线程开启后");

            Task.WaitAll(tasks);
            Console.WriteLine($"time1:{times[0]}, time2:{times[1]}, time3:{times[2]}, time4:{times[3]}, bindtime:{bindtime}");

        }

        private void DoTask(int n)
        {
            double sum = 9999999999;
            for (int i = 0; i < n; i++)
            {
                sum /= (i + 1)*(i+1);
            }
        }

        private void PrintProcessInfo(string info)
        {
            var p = Process.GetCurrentProcess();
            var threads = p.Threads;
            Console.WriteLine($"{info}:当前进程共有{threads.Count}个线程");
        }

        private void BindThreadToCpu(int core)
        {
            var p = Process.GetCurrentProcess();
            var threads = p.Threads;

            if (core >= 0)
            {
                for (int i = 0; i < threads.Count; i++)
                {
                    var item = threads[i];

                    //将线程绑定到某个核上
                    item.ProcessorAffinity = (IntPtr)(core + 1);
                    item.IdealProcessor = core;
                }
            }
        }
        
    }
    class Program
    {
        static void Main(string[] args)
        {
            new Threads().Start();

            Console.WriteLine($"执行完成,按任意键结束");
            Console.Read();
        }
    }
}

 

posted @ 2020-12-18 15:53  时空观察者9号  阅读(226)  评论(0编辑  收藏  举报