73
\$\begingroup\$

Task

Using any type of parallelisation, wait multiple periods, for a total sleep time of at least a minute (but less than a minute and a half).

The program/function must terminate within 10 seconds and return (by any means and in any format) two values: the total elapsed time, and the total executed sleep time. Both time values have to have a precision of at least 0.1 seconds.

This is similar to the concept of man-hours: a job that takes 60 hours can be completed in only 6 hours if 10 workers are splitting the job. Here we can have 60 seconds of sleep time e.g. in 10 parallel threads, thus requiring only 6 seconds for the whole job to be completed.

Example

The program MyProgram creates 14 threads, each thread sleeps for 5 seconds:

MyProgram[5.016,70.105]

The execution time is greater than 5 seconds, and the total sleep time is greater than 70 seconds because of overhead.

\$\endgroup\$
  • 2
    \$\begingroup\$ I've read the question several times and I don't get it. Can you clarify a bit? Why "10 seconds" and a delay of "70 seconds"? How are all those times related? \$\endgroup\$ – Luis Mendo Jun 16 '16 at 7:31
  • 3
    \$\begingroup\$ How many threads can we assume will be executed in parallel? \$\endgroup\$ – miles Jun 16 '16 at 7:47
  • 3
    \$\begingroup\$ What precision is required for the time in output? \$\endgroup\$ – edc65 Jun 16 '16 at 9:15
  • 22
    \$\begingroup\$ I wonder if this will cause all the golfing language authors to engage in a mad dash to add multi-threading to their creations... \$\endgroup\$ – Adám Jun 16 '16 at 14:23
  • 3
    \$\begingroup\$ @NoOneIsHere Ah, well, a properly implemented sleep method should not busy a core, so the number of threads may exceed the number of (virtual) processors. \$\endgroup\$ – Adám Jun 16 '16 at 15:08

34 Answers 34

1
2
1
\$\begingroup\$

Common Lisp (Lispworks), 457 bytes

(defun f(n)(labels((h(n b v)(mp:process-run-function nil nil #'(lambda(b v)(progn(let((s(get-internal-real-time)))(sleep 5)(setf(svref v n)(-(get-internal-real-time)s)))(mp:barrier-wait b :pass-through t)))b v)))(let((s(get-internal-real-time))(e 0)(q 0)(v(make-sequence 'vector n :initial-element 0))(b(mp:make-barrier(1+ n))))(dotimes(i n)(h i b v))(mp:barrier-wait b)(setf e(-(get-internal-real-time)s))(dotimes(p n)(setf q(+ q(svref v p))))(list e q))))

ungolfed:

    (defun f (n-thread)
      (labels ((my-process (process-name n barrier vec)
                 (mp:process-run-function
                  process-name
                  nil
                  #'(lambda (barrier vec)
                      (progn
                        (let ((start-time (get-internal-real-time)))
                          (sleep 5)
                          (setf (svref vec n)
                                (- (get-internal-real-time) start-time)))
                        (mp:barrier-wait barrier :pass-through t)))
                  barrier
                  vec)))

        (let ((total-start-time (get-internal-real-time))
              (total-time 0)
              (sum-per-process-time 0)
              (vector (make-sequence 'vector n-thread :initial-element 0))
              (barrier (mp:make-barrier (1+ n-thread))))
          (dotimes (i n-thread)
            (my-process
             (concatenate 'string "process-" (write-to-string i))
             i
             barrier
             vector))
          (mp:barrier-wait barrier)
          (setf total-time (- (get-internal-real-time) total-start-time))
          (dotimes (p n-thread)
            (setf sum-per-process-time
                  (+ sum-per-process-time (svref vector p))))
          (list total-time sum-per-process-time))))

Usage:

CL-USER 1 > (f 14)
(5028 70280)
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

C#, 131 bytes

The following start 9 threads that each wait 6667 milliseconds.
The program run in 6.73 secondes and has the following output : 00:00:06.7116711|604140408
Where "604140408" is the number of tick.
There are 10 000ticks is a millisecond.
So this give ~60.414 seconds. Total execution time and wait time don't have the same output format for golfing reason.

using t=DateTime;var s=t.Now;Task.WhenAll(new t[9].Select(y=>Task.Delay(6667))).Wait();Debug.Write(t.Now-s+"|"+(t.Now-s).Ticks*9);

Here is a fiddle that exceed the limit of execution of time of fiddle. Lower "6667" so that it fix fiddle's criteria if you want to run it.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I don't know C#, but it looks like you do not measure the elapsed sleep time, rather you use a hard-coded value. \$\endgroup\$ – Adám Jun 17 '16 at 16:50
  • \$\begingroup\$ @Adám, yes indeed I don't measure it because I might not understand something. If I tell all threads to wait for a total time of 60003 milli, what is the point of adding extra execution lines to count the time elapsed since I already know the time? If I add time checking, it's going to take longer only because of the execution time of extra line of code. Beside I wouldn't know how to accurately dissociate wait time from execution time. eg: execution time is 6722 milli and threads waits for 6667 each. So there is a 55milli left for code execution . [See next comment] \$\endgroup\$ – AXMIM Jun 17 '16 at 17:25
  • \$\begingroup\$ @Adám There may be a small amount of overhead waiting in these 55milli, but I don't understand what you really want about it. The only thing that I could easily calculate is the time it's took to launch all nice thread because first started thread will wait a little longer then the last one. But we are talking about few milliseconds here. So I didn't bother to do it, because yet again I thing I'm missing what you want exactly. I apologize for not getting it, but may be you can shed some light on what is confusing me? \$\endgroup\$ – AXMIM Jun 17 '16 at 17:31
  • 1
    \$\begingroup\$ The point of this challenge is to start sleeping threads and keep track of their running time. One simple way to do this is take the time before launching the threads, and subtract that from the time when the last thread terminates. \$\endgroup\$ – Adám Jun 17 '16 at 19:20
  • \$\begingroup\$ I updated the answer to take the existing time differences between before launching threads and last thread terminates multiplied for the number of thread. \$\endgroup\$ – AXMIM Jun 20 '16 at 20:03
1
\$\begingroup\$

c++, 332 358 357 bytes

Thanks Adám!

#include <iostream>
#include <chrono>
#include <thread>
#define n(x)auto x=chrono::steady_clock::now();
using namespace std;double t=0;void f(){n(s)this_thread::sleep_for(chrono::seconds(9));n(e)t+=(e-s).count()/1e9;}int main(){int i;n(s)thread*a[7];for(i=0;i<7;i++)a[i]=new thread(f);for(i=0;i<7;i++)a[i]->join();n(e)cout<<t<<","<<(e-s).count()/1e9<<"\n";}

Try it online

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

R + Snowfall, 67 UTF-8 bytes

library(snowfall)
sfInit(T,8)
sfSapply(1:8,function(j)Sys.sleep(8))
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Hello, and welcome to PPCG! This is code-golf so you must include your byte count. If you accept my edit, you don't have to worry about it. \$\endgroup\$ – NoOneIsHere Jun 17 '16 at 16:15
  • \$\begingroup\$ You also need to include in your header Snowfall. \$\endgroup\$ – NoOneIsHere Jun 17 '16 at 16:26
  • \$\begingroup\$ How does the output look? \$\endgroup\$ – Adám Jun 17 '16 at 16:51
  • \$\begingroup\$ What is a "UTF-8 byte"? \$\endgroup\$ – Adám Jun 17 '16 at 19:21
  • 2
    \$\begingroup\$ @Adám: The byte counting userscript I use says "Winner: JDL's answer at -8 bytes". \$\endgroup\$ – NoOneIsHere Jul 2 '16 at 14:52
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.