5 ms·
Fun with Timers and Cpuid
- cmeacham98 6y agoIt seems like you can only make this mistake if you assume that Intel CPUs always use the frequency from the CPUID name for timer ticks, which seems like a dangerous assumption even today (I'd love to see someone test this on a CPU with an overclocked BCLK).
- scaramanga 6y agoAs far as I can tell it is false: model name : Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz cpu MHz : 2600.028 But tsc clock freq according to max non-turbo ration reported by MSR 0xce is 28 (* 100MHz) = 2.8GHz As I understand it, tsc ticks at a constant rate according to this value.
- jfrunyon 6y agoIndeed it seems a dangerous assumption, considering the Intel Software Developer's Manual explicitly says it's not true... > For [big list of models]: the time-stamp counter increments at a constant rate. That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may differ from the processor base frequency, see Section 18.7.2 for more detail. On certain processors, the TSC frequency may not be the same as the frequency in the brand string. (Vol 3B § 17.17 / PDF page 3443 https://software.intel.com/content/www/us/en/develop/articles/intel-sdm.html https://software.intel.com/content/www/us/en/develop/article...)
- saagarjha 6y agoIf you'd like to skip the assembly, on macOS, mach_absolute_time is generally the highest resolution timer you are going to get (it reads the relevant hardware registers). Its resolution is easy to get, both on ARM: $ swift Welcome to Apple Swift version 5.4 (swiftlang-1205.0.26.4 clang-1205.0.19.54). Type :help for assistance. 1> import Darwin 2> var timebase = mach_timebase_info_data_t(); mach_timebase_info(&timebase) $R0: kern_return_t = 0 timebase: mach_timebase_info_data_t = { numer = 125 denom = 3 } 3> 125.0 / 3.0 $R1: Double = 41.666666666666664 and Intel: $ swift Welcome to Apple Swift version 5.4 (swiftlang-1205.0.26.4 clang-1205.0.19.54). Type :help for assistance. 1> import Darwin 2> var timebase = mach_timebase_info_data_t(); mach_timebase_info(&timebase) $R0: kern_return_t = 0 timebase: mach_timebase_info_data_t = { numer = 1 denom = 1 } 3> 1.0 / 1.0 $R1: Double = 1
- mhh__ 6y agoThis is also doesn't mention that rdtsc and it's brother rdtscp should usually be used with a serializing instruction for small measurements. And/or a fence depending on what you want to measure. I'm interested how they are translated.
- jcownie 6y ago(This is Jim, the author of the blog :-)). I do mention that in the reply to one of the comments there. (As well as explicitly saying in the text that that whole subject was too large to include). if you comment there you're much more likely to get a reply!
- mhh__ 6y agoOK I must have missed that it had comments on the article. If you're looking for a new subject to cover, M1 seems to be vulnerable to spectre
- appleflaxen 6y agoDoes Apple need permission from Intel for their CPU to make an API "claim" to being a GenuineIntel brand processor? This seems like it could be a tricky legal corner, if it's not already established by these business partners.
- bombcar 6y agoIt likely falls under "interoperability" and I'm sure things like VMWare et al have been doing similar for years.
- jfrunyon 6y agoMost virtual machines either have their own branding in CPUID, or pass through the host CPUID.
- seedless-sensat 6y agoBrowser user agents come to mind as a similar compatibility trick of yore.
- deleted 6y ago[deleted]
- saurik 6y agoThis was established in Sega v. Accolade: if using trademark is required for interoperability, then that's fair game.
- appleflaxen 6y agoThank you for the clarification and citation. Your answer is the best of several.
- jfrunyon 6y ago> Intel have specified a cpuid leaf that gives us that information (leaf 15H), however they only did so relatively recently, and I have yet to see a CPU that implements this. (The code checks for it, and will use it if it can, but it’s clearly not a general solution, and obviously hasn’t been tested :-)). FYI, Intel does list some nominal values for what the code calls 'coreCrystalFreq' (15H.ECX), in Vol. 3B§18.7.3. In my situation (i7-8559U, I don't have a compiler on anything newer), I do have 15H.EAX and 15H.EBX, and if I patch out the check for 15H.ECX and replace it with the constant given in the SDM for "6th and 7th generation Intel® Core™ processors", it's sane: cpuid leaf 15H: coreCrystal = 24, eax=2, ebx=226, ecx=0 => 368.73 us Sanity check against std::chrono::steady_clock gives frequency 2.71 GHz => 368.75 ps Measured granularity = 14 ticks => 192.86 MHz, 5.19 ns From model name string frequency 2.70 GHz => 370.37 ps (Also, I needed #include <cstdarg> to compile, since that's where va_start is defined....) > While there is no specification that requires that [the model name frequency] is the same as the notional time-stamp counter rate, so far I haven’t seen an Intel processor where it is different. Intel explicitly states that this is not a valid assumption. Vol.3B§17.17 Other than that... why not determine the rate of the counter by comparing against comparing against a counter of known rate? Which is what you do for a "sanity check" anyway! And is probably what the OS does! Or, better yet, admit the truth: none of these counters are appropriate for absolute measurement, especially at nanosecond scale. They are only appropriate for relative measurement, between two samples from a single device around the same time.
- throwawaye345 6y agoI definitely read this as fun with tinder and okcupid before double checking my eyesight
- eqvinox 6y agoIs the overhead of calling a library function actually significantly higher than the serialization overhead that RDTSC already incurs? It's paying that price anyway, and if that shadows the cycles spent on the call and its overhead, it would be preferable to just call a library function...