दूसरे के एक अंश के लिए सोने के लिए लूप चाहिए


14

मेरी मशीन पर मुझे एक चक्र को निष्पादित करने की आवश्यकता है जो 1 सरल कमांड को पुनरावृत्त करता है जिसमें दूसरे के अंशों में व्यक्त देरी होनी चाहिए।

मान लीजिए कि मुझे जरूरत है:

  • इस तरह के उदाहरण के लिए कुछ तुच्छ द्वारा उत्पन्न एक बढ़ती कुंडली (फ़ाइल -0, फ़ाइल -1, फ़ाइल -2, ...) के साथ एक फ़ाइल को बचाने के लिए time > file-$x
  • मुझे इसे प्रत्येक 1/70 सेकंड (उदाहरण के रूप में) करने की आवश्यकता है क्योंकि मैं अपना समय दूसरे के अंशों के साथ व्यक्त करना चाहूंगा।

मैं वास्तव में सटीक कैसे हो सकता हूं और सब कुछ एक बैश स्क्रिप्ट के साथ व्यक्त किया गया है?

अंश एक अनिश्चित मात्रा उत्पन्न कर सकता है, मुझे सटीक होने की आवश्यकता है और इसलिए मुझे कम से कम 4-5 दशमलव की आवश्यकता है।

जवाबों:


12

बैश में भिन्न से दशमलव में परिवर्तित करने के लिए, कुछ ऐसा करें

myvar=$(echo "scale=4; 5/10" | bc)

फिर, उस मूल्य पर एक लूप करने के लिए,

for i in $(seq 1 1000); do sleep $myvar; done

डेबियन (GNU) पर मेरी नींद का क्रियान्वयन दशमलव नींद के मूल्यों को स्वीकार करता है।

दुर्भाग्य से ..

उस तरह की परिशुद्धता (4-5 दशमलव स्थानों) के साथ, आप एक पर्ल स्क्रिप्ट या संकलित प्रोग्राम जैसा कुछ चाहते हैं; लूप के भीतर किसी भी प्रोग्राम को कॉल करने के ओवरहेड में बहुत अधिक घबराना है। नींद को खुद बुलाकर कुछ मिलीसेकंड लगेगा।

निम्नलिखित पर विचार करें, एक दूसरी नींद के 1 / 10,000 वें, 1000 बार किया गया:

time for i in $(seq 1 1000); do sleep 0.0001; done

real    0m2.099s
user    0m3.080s
sys     0m1.464s

अपेक्षित परिणाम एक सेकंड का 1/10 वां होगा। नींद अब आपके द्वारा सहिष्णुता के पास नहीं है।

/programming/896904/how-do-i-sleep-for-a-millisecond-in-perl

पर्ल के समय का उपयोग :: HiRes, 1000 * 1000 माइक्रोसेकंड:

my $i=0;
for($i=0;$i<=1000;$i++) {
        usleep(1000);
}

real    0m1.133s
user    0m0.024s
sys     0m0.012s

हमें एक सेकंड के लिए बहुत करीब देता है।


अगर यह 4-5 डेसीमल हासिल करना संभव नहीं है, तो मैं एक विकल्प के रूप में सबसे अच्छा संभव परिणाम ले सकता हूं, लेकिन मेरी बात यह है कि मुझे इसे भिन्न या सेकंड में व्यक्त करने की आवश्यकता है।
user1717079

बैश सहित किसी भी स्क्रिप्टिंग भाषा में एक अंश को दशमलव में बदलना पूरी तरह से मामूली होगा। उदा। "स्केल = 4; 5/10" बीसी
रोब बॉश

अब मुझे पता चला है कि अभिव्यक्ति को कैसे बदलना है, अब समस्या यह है कि एक साधारण बैश यह वास्तव में धीमा है और बस इस आवृत्ति के साथ नहीं रह सकता है ...
user1717079

हाँ, यदि आप एक सेकंड के लगभग 1/10 वें भाग की तुलना में कुछ अधिक सटीक चाहते हैं, तो आप संभवतः पर्ल या पायथन चाहते हैं ताकि लूप के भीतर ओवरहेड कॉलिंग प्रोग्राम से बचा जा सके।
रोब बॉश

7

शायद आप बस चला सकते हैं

sleep 0.7

?

man 1 sleep

मेरे archlinuxडिस्ट्रो पर:

NUMBER सेकंड के लिए विराम दें। SUFFIX सेकंड के लिए 's' हो सकता है (डिफ़ॉल्ट), मिनट के लिए 'm', घंटे के लिए 'h' या दिनों के लिए 'd' हो सकता है। अधिकांश कार्यान्वयनों के विपरीत, जिनके लिए NUMBER की आवश्यकता होती है एक पूर्णांक होता है, यहां NUMBER एक मनमाना फ्लोटिंग पॉइंट संख्या हो सकती है। दो या अधिक तर्कों को देखते हुए, उनके मूल्यों के योग द्वारा निर्दिष्ट समय की मात्रा के लिए रुकें।


sleepभिन्नों की अनुमति देता है? क्या आप एक नकली लूप के साथ एक पूर्ण उदाहरण पेश कर सकते हैं?
user1717079

0.7 यह एक अंश नहीं है जो मेरी समस्या को व्यक्त करता है ... मेरी समस्या ग्रैन्युलैरिटी के बारे में है; 1/3 के बारे में सोचो और नींद के साथ सटीक होने की कोशिश करो।
user1717079

6

एक प्रक्रिया को शुरू करने और इसमें एक नया निष्पादन योग्य लोड करने के लिए कुछ मिलिसेकंड लेने की संभावना है, इसलिए उस तरह की परिशुद्धता वास्तव में समझ में नहीं आती है। यह भी ध्यान दें कि कई प्रणालियों पर सीपीयू समय 10ms तक के स्लाइस द्वारा प्रक्रियाओं को आवंटित किया जाता है।

यह कहते हुए कि, कुछ sleepकार्यान्वयन सेकंड के अंशों को लेते हैं, और zsh और ksh93 दोनों अपने $SECONDSविशेष चर को भिन्नात्मक बना सकते हैं typeset -F SECONDS

उदाहरण (zsh):

$ typeset -F SECONDS=0; for ((i=1; i<=70; i++)); do sleep $((1./70)); date +%s.%N; done | { head -n3;echo ..;tail -n3; }; echo $SECONDS
1350076317.374870501
1350076317.391034397
1350076317.407278461
..
1350076318.464585550
1350076318.480887660
1350076318.497133050
1.1393780000

उफ, यह सूख गया। आप इसके आधार पर सोने के समय को समायोजित कर सकते हैं $SECONDS:

$ typeset -F SECONDS=0; for ((i=1; i<=70; i++)); do sleep $((i/70. - SECONDS)); date +%s.%N; done | { head -n3;echo ...;tail -n3; }; echo $SECONDS
1350076420.262775654
1350076420.277012997
1350076420.291302750
../..
1350076421.219682227
1350076421.234134663
1350076421.248255685
1.0020580000

उन 2 अतिरिक्त मिलिसेकंड को शायद आखिरी sleepऔर dateआज्ञाओं को चलाने के लिए जिम्मेदार माना जाता है ।

यह भी ध्यान दें कि zselectएक सेकंड के सौवें भाग में व्यक्त टाइमआउट के साथ zsh में एक बिल्डिन है । और ksh93 ने sleep(और फ्लोटिंग पॉइंट को स्वीकार किया है) बनाया है और इसकी printfतिथि / समय प्रिंट कर सकते हैं।

$ typeset -F SECONDS=0; for ((i=1; i<=70; i++)); do ((i<4 || i>67)) && printf '%(%S.%N)T\n' now; sleep $((i/70.-SECONDS)); done; echo $SECONDS
20.823349000
20.837510000
20.851663000
21.780099000
21.794254000
21.808405000
0.9992358685

यदि आप कुछ अधिक सटीक चाहते हैं, तो आप शायद वास्तविक समय क्षमताओं के साथ एक वास्तविक समय ऑपरेटिंग सिस्टम या एक ऑपरेटिंग सिस्टम चाहते हैं और निश्चित रूप से शेल का उपयोग नहीं करते हैं।


sleep 1/70मेरी मशीन पर अनुमति नहीं है ...
user1717079

मैं जो हासिल करना चाहता हूं, उसके करीब भी नहीं, मैं चीजों को कैसे तेजी से निष्पादित कर सकता हूं?
user1717079

क्षमा करें, भिन्नात्मक रूप से, मेरा मतलब यह नहीं था कि n / m के रूप में व्यक्त किया जाए जहाँ n और m पूर्णांक हैं, लेकिन एक भिन्नात्मक भाग के साथ दशमलव के रूप में। मुझे लगता है कि आप उन्हें दशमलव फ़्लोटिंग पॉइंट संख्या भी कह सकते हैं, हालांकि मैं उचित अंग्रेजी शब्दावली के बारे में निश्चित नहीं हूं
स्टीफन चेज़लस

मुझे लगता है कि मैं शेल से बचने के लिए जा रहा हूं ...
user1717079

उत्तर देने वाला सही है। शेल और प्रक्रियाएं आमतौर पर मिलीसेकंड रिज़ॉल्यूशन के अनुकूल नहीं होती हैं। विश्वसनीय प्रदर्शन के लिए, आपको एक प्रोग्राम को संकलित करने की आवश्यकता होगी, जो हमें फोन करता है (3) या जैसे - और आपको अलग-अलग कॉन्फ़िगरेशन के साथ अपने कर्नेल को फिर से जोड़ने की आवश्यकता हो सकती है; या कम से कम अपने कर्नेल के रनटाइम शेड्यूलर को अलग-अलग पैरामीटर फ़ीड करें। यह करने के लिए nontrivial है। एक मानक कर्नेल के साथ एक मानक डेबियन इंस्टॉलेशन में सीमित रियलटाइम क्षमताएं हैं। फिर भी, आप अच्छा (1) कमांड देखना चाहते हैं; यह मदद कर सकता है।
thb

3

यदि आपका शेल sleepअंश स्वीकार नहीं करता है, तो पर्ल का उपयोग करें।

sleep_fraction() {
  /usr/bin/perl -e "select(undef, undef, undef, $1)"
}

sleep_fraction 0.01428

यदि आपको अंश का पता लगाने की आवश्यकता है, तो उपयोग करें echo "scale=5; 1/70" | bc


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.