Finding out the CPU clock frequency (per core, per processor)

前端 未结 6 1910
无人及你
无人及你 2020-11-30 01:26

Programs like CPUz are very good at giving in depth information about the system (bus speed, memory timings, etc.)

However, is there a programmatic way of calculatin

6条回答
  •  南方客
    南方客 (楼主)
    2020-11-30 01:57

    I realise this has already been answered. I also realise this is basically a black art, so please take it or leave it - or offer feedback.

    In a quest to find the clock rate on throttled (thanks microsft,hp, and dell) HyperV hosts (unreliable perf counter), and HyperV guests (can only get stock CPU speed, not current), I have managed, through trial error and fluke, to create a loop that loops exactly once per clock.

    Code as follows - C# 5.0, SharpDev, 32bit, Target 3.5, Optimize on (crucial), no debuger active (crucial)

            long frequency, start, stop;
            double multiplier = 1000 * 1000 * 1000;//nano
            if (Win32.QueryPerformanceFrequency(out frequency) == false)
                throw new Win32Exception();
    
            Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
            const int gigahertz= 1000*1000*1000;
            const int known_instructions_per_loop = 1; 
    
            int iterations = int.MaxValue;
            int g = 0;
    
            Win32.QueryPerformanceCounter(out start);
            for( i = 0; i < iterations; i++)
            {
                g++;
                g++;
                g++;
                g++;
            }
            Win32.QueryPerformanceCounter(out stop);
    
            //normal ticks differs from the WMI data, i.e 3125, when WMI 3201, and CPUZ 3199
            var normal_ticks_per_second = frequency * 1000;
            var ticks = (double)(stop - start);
            var time = (ticks * multiplier) /frequency;
            var loops_per_sec = iterations / (time/multiplier);
            var instructions_per_loop = normal_ticks_per_second  / loops_per_sec;
    
            var ratio = (instructions_per_loop / known_instructions_per_loop);
            var actual_freq = normal_ticks_per_second / ratio;
    
            Console.WriteLine( String.Format("Perf counhter freq: {0:n}", normal_ticks_per_second));
            Console.WriteLine( String.Format("Loops per sec:      {0:n}", loops_per_sec));
            Console.WriteLine( String.Format("Perf counter freq div loops per sec: {0:n}", instructions_per_loop));
            Console.WriteLine( String.Format("Presumed freq: {0:n}", actual_freq));
            Console.WriteLine( String.Format("ratio: {0:n}", ratio));
    

    Notes

    • 25 instructions per loop if debugger is active
    • Consider running a 2 or 3 seconds loop before hand to spin up the processor (or at least attempt to spin up, knowing how heavily servers are throttled these days)
    • Tested on a 64bit Core2 and Haswell Pentium and compared against CPU-Z

提交回复
热议问题