Ona kayan nokta numaraları verebilirim, örneğin
time.sleep(0.5)
ama ne kadar doğru? Eğer verirsem
time.sleep(0.05)
gerçekten yaklaşık 50 ms uyuyacak mı?
Yanıtlar:
Time.sleep işlevinin doğruluğu, temelde yatan işletim sisteminizin uyku doğruluğuna bağlıdır. Stok Windows gibi gerçek zamanlı olmayan işletim sistemleri için uyuyabileceğiniz en küçük aralık yaklaşık 10-13 ms'dir. Minimum 10-13 ms'nin üzerindeyken birkaç milisaniye içinde doğru uykular gördüm.
Güncelleme: Aşağıda belirtilen belgelerde bahsedildiği gibi, sizi erken uyandırırsa tekrar uykuya dönmenizi sağlayacak bir döngüde uykuyu yapmak yaygındır.
Ayrıca Ubuntu kullanıyorsanız, rt çekirdek paketini (en azından Ubuntu 10.04 LTS'de) kurarak sözde gerçek zamanlı bir çekirdeği (RT_PREEMPT yama setiyle) deneyebileceğinizi de belirtmeliyim.
DÜZENLEME: Gerçek zamanlı olmayan Linux çekirdeklerinin düzeltilmesi, 1ms'den 10ms'ye çok daha yakın minimum uyku aralığına sahiptir, ancak deterministik olmayan bir şekilde değişir.
sleep()
, belgelerden daha önemli bir şey yapmakla meşgullerse "askıya alma süresi, sistemdeki diğer etkinlik ".
İnsanlar işletim sistemleri ve çekirdekler arasındaki farklar konusunda oldukça haklılar, ancak Ubuntu'da herhangi bir ayrıntı görmüyorum ve MS7'de 1 ms'lik bir ayrıntı görüyorum. Time.sleep'nin farklı bir uygulamasını önermek, yalnızca farklı bir tik hızı değil. Daha yakından inceleme, bu arada Ubuntu'da 1μs ayrıntı düzeyi önerir, ancak bu, doğruluğu ölçmek için kullandığım time.time işlevinden kaynaklanıyor.
Gönderen belgeler :
Öte yandan, hassas
time()
vesleep()
Unix eşdeğer daha iyidir: kez kayan nokta sayısı olarak ifade edilirtime()
, en doğru zaman döner (Unix kullanılarakgettimeofday
temin edilebilir), vesleep()
UNIX (sıfır olmayan bir fraksiyonu ile bir saat kabulselect
kullanılan mümkün olan yerlerde bunu uygulamak için).
Ve daha spesifik wrt sleep()
:
Verilen saniye sayısı boyunca yürütmeyi askıya alın. Argüman, daha kesin bir uyku süresini belirtmek için bir kayan nokta numarası olabilir. Gerçek askıya alma süresi talep edilenden daha az olabilir çünkü yakalanan herhangi bir sinyal
sleep()
, o sinyalin yakalama rutininin müteakip yürütülmesini sona erdirecektir . Ayrıca, sistemdeki diğer aktivitelerin programlanması nedeniyle askıya alma süresi keyfi bir miktar tarafından talep edilenden daha uzun olabilir .
İşte Wilbert'in cevabının devamı: Mac OS X Yosemite için de aynısı, çünkü henüz pek bahsedilmedi.
Çoğu zaman talep ettiğiniz sürenin 1.25 katı kadar uyuyor ve bazen de talep ettiğiniz sürenin 1 ile 1.25 katı arasında uyuyor. Neredeyse hiçbir zaman (1000 numunenin ~ iki katı), talep ettiğiniz sürenin 1,25 katından önemli ölçüde daha fazla uyumaz.
Ayrıca (açıkça gösterilmemiştir) 1.25 ilişkisi, yaklaşık 0.2 ms'nin altına inene kadar oldukça iyi durumda görünüyor, ardından biraz bulanıklaşmaya başlıyor. Ek olarak, istenen süre 20 ms'nin üzerine çıktıktan sonra gerçek süre, isteğinizden yaklaşık 5 ms daha uzun sürecek gibi görünüyor.
Yine, sleep()
OS X'te Windows veya hangi Linux kernal Wilbert'in kullandığı uygulamadan tamamen farklı bir uygulama gibi görünüyor .
Neden öğrenmiyorsun:
from datetime import datetime
import time
def check_sleep(amount):
start = datetime.now()
time.sleep(amount)
end = datetime.now()
delta = end-start
return delta.seconds + delta.microseconds/1000000.
error = sum(abs(check_sleep(0.050)-0.050) for i in xrange(100))*10
print "Average error is %0.2fms" % error
Kayıt için, her iki linux makinesinde HTPC'imde 0.1ms ve dizüstü bilgisayarımda 2ms hata alıyorum.
Uyku () hakkında hiçbir şey garanti edemezsiniz, ancak en azından siz söylediğiniz sürece uyumak için en iyi çabayı gösterecektir (sinyaller uykunuzu zaman dolmadan öldürebilir ve daha birçok şey onu çalıştırabilir. uzun).
Elbette standart bir masaüstü işletim sisteminde elde edebileceğiniz minimum miktar 16 ms civarında olacaktır (zamanlayıcı ayrıntı düzeyi artı bağlam değiştirme süresi), ancak, siz denediğinizde sağlanan bağımsız değişkenden% sapma büyük olasılıkla önemli olacaktır. 10s milisaniye uyumak.
Sinyaller, GIL'i tutan diğer iş parçacıkları, çekirdek zamanlama eğlencesi, işlemci hızı adımlaması vb., İş parçacığınızın / işleminizin gerçekte uykuda olduğu süre boyunca hasara neden olabilir.
Bunu yakın zamanda Windows 10 üzerinde Python 3.7'de test etti. Hassasiyet 1 ms civarındaydı.
def start(self):
sec_arg = 10.0
cptr = 0
time_start = time.time()
time_init = time.time()
while True:
cptr += 1
time_start = time.time()
time.sleep(((time_init + (sec_arg * cptr)) - time_start ))
# AND YOUR CODE .......
t00 = threading.Thread(name='thread_request', target=self.send_request, args=([]))
t00.start()
Sleep () argümanını iletmek için bir değişken kullanmayın, hesaplamayı doğrudan sleep'e () eklemelisiniz.
Ve terminalimin dönüşü
1 ───── 17:20: 16.891 ───────────────────
2 ───── 17: 20: 18,891 ───────────────────
3 ───── 17:20: 20.891 ───────────────────
4 ───── 17: 20: 22,891 ───────────────────
5 ───── 17:20: 24.891 ───────────────────
....
689 ─── 17: 43: 12.891 ────────────────────
690 ─── 17: 43: 14.890 ────────────────────
691 ─── 17: 43: 16.891 ────────────────────
692 ─── 17: 43: 18,890 ────────────────────
693 ─── 17: 43: 20.891 ────────────────────
...
727 ─── 17: 44: 28.891 ────────────────────
728 ─── 17: 44: 30.891 ────────────────────
729 ─── 17: 44: 32.891 ────────────────────
730 ─── 17: 44: 34,890 ────────────────────
731 ─── 17: 44: 36.891 ────────────────────
def test():
then = time.time() # get time at the moment
x = 0
while time.time() <= then+1: # stop looping after 1 second
x += 1
time.sleep(0.001) # sleep for 1 ms
print(x)
Windows 7 / Python 3.8'de 1000
, uyku değerini şu şekilde ayarlasam bile benim için geri döndü0.0005
yani mükemmel bir 1 ms