gpt4 book ai didi

ruby - Ruby 中的亚毫秒时间测量

转载 作者:数据小太阳 更新时间:2023-10-29 08:36:24 27 4
gpt4 key购买 nike

我在 Rubymine 8.0.3 中运行 Ruby 2.2

我的机器运行的是带有英特尔酷睿 i7-4710MQ 的 Windows 7 Pro

我已经能够在这台机器上使用 C++、Java、Python 和 JS 实现 ~411 ns 的精度,但似乎无法在 Ruby 中找到实现这种性能的方法,因为内置的 Time 库很好仅适用于女士。

我可以对我的测试进行编程以容忍这种降低的精度,但是是否可以合并 Windows QPC API 以改进对执行时间的评估?

我确定时钟滴答精度的测试代码如下:

numTimes = 10000
times = Array.new(numTimes)

(0...(numTimes)).each do |i|
times[i] = Time.new
end

durations = []
(0...(numTimes - 1)).each do |i|
durations[i] = times[i+1] - times[i]
end

# Output duration only if the clock ticked over
durations.each do |duration|
if duration != 0
p duration.to_s + ','
end
end

下面的代码合并了找到的 QPC here

require "Win32API"

QueryPerformanceCounter = Win32API.new("kernel32",
"QueryPerformanceCounter", 'P', 'I')
QueryPerformanceFrequency = Win32API.new("kernel32",
"QueryPerformanceFrequency", 'P', 'I')

def get_ticks
tick = ' ' * 8
get_ticks = QueryPerformanceCounter.call(tick)
tick.unpack('q')[0]
end

def get_freq
freq = ' ' * 8
get_freq = QueryPerformanceFrequency.call(freq)
freq.unpack('q')[0]
end

def get_time_diff(a, b)
# This function takes two QPC ticks
(b - a).abs.to_f / (get_freq)
end

numTimes = 10000
times = Array.new(numTimes)

(0...(numTimes)).each do |i|
times[i] = get_ticks
end

durations = []
(0...(numTimes - 1)).each do |i|
durations[i] = get_time_diff(times[i+1], times[i])
end

durations.each do |duration|
p (duration * 1000000000).to_s + ','
end

此代码在我的机器上返回约 22-75 微秒的滴答声之间的持续时间

最佳答案

使用Process::clock_gettime可以获得更高的精度:

Returns a time returned by POSIX clock_gettime() function.

这是一个 Time.now 的例子

times = Array.new(1000) { Time.now }
durations = times.each_cons(2).map { |a, b| b - a }

durations.sort.group_by(&:itself).each do |time, elements|
printf("%5d ns x %d\n", time * 1_000_000_000, elements.count)
end

输出:

    0 ns x 686
1000 ns x 296
2000 ns x 12
3000 ns x 2
12000 ns x 2
18000 ns x 1

下面是使用 Process.clock_gettime 的相同示例:

times = Array.new(1000) { Process.clock_gettime(Process::CLOCK_MONOTONIC) }

输出:

  163 ns x 1
164 ns x 1
164 ns x 9
165 ns x 6
165 ns x 22
166 ns x 39
166 ns x 174
167 ns x 13
167 ns x 129
168 ns x 95
168 ns x 32
169 ns x 203
169 ns x 141
170 ns x 23
170 ns x 37
171 ns x 30
171 ns x 3
172 ns x 24
172 ns x 10
174 ns x 1
175 ns x 2
180 ns x 1
194 ns x 1
273 ns x 1
2565 ns x 1

这是一个快速并排比较:

array = Array.new(12) { [Time.now, Process.clock_gettime(Process::CLOCK_MONOTONIC)] }

array.shift(2) # first elements are always inaccuate
base_t, base_p = array.first # baseline

printf("%-11.11s %-11.11s\n", 'Time.now', 'Process.clock_gettime')
array.each do |t, p|
printf("%.9f %.9f\n", t - base_t, p - base_p)
end

输出:

Time.now    Process.clo
0.000000000 0.000000000
0.000000000 0.000000495
0.000001000 0.000000985
0.000001000 0.000001472
0.000002000 0.000001960
0.000002000 0.000002448
0.000003000 0.000002937
0.000003000 0.000003425
0.000004000 0.000003914
0.000004000 0.000004403

这是在 Intel Core i7 上运行的 OS X 上的 Ruby 2.3,Windows 不确定。

为避免 float 转换造成精度损失,您可以指定其他单位,例如:

Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
#=> 191519383463873

关于ruby - Ruby 中的亚毫秒时间测量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35790966/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com