Optimized Thread Scheduling
Question: The 'peach' keyword in q allows for the user to run a function over multiple threads. The number of threads spawned is equal to the number of slaves enabled (-s flag commandline, \s runtime). Q distributes jobs to threads in round robin fashion at invocation. For example, with 2 threads, "f peach `a`b`c`d" will have `a and `c assigned to Thread 1, `b and `d assigned to Thread 2. This is not optimal because you can have the case where load is not balanced amongst threads, which will result in a state where some threads are working while others are idle. This will slow down the execution speed of the multi-threaded function, as the speed is bounded by the last thread to finish. Luckily, we can implement our own thread scheduling (written in C) such that no thread sits idle. Whenever a thread finishes execution, it will take on the next item. In this example, we will be implementing an optimized multi-threaded version of nanosleep. The function is defined as 'psleep' and takes in 2 K objects as arguments, a list and number denoting number of threads to use.
q)\s 2 q)psleep:`threads 2: (`psleep;2) / load 'psleep' from shared library (threads.so) q)sleep:`threads 2: (`nsleep;1) / load 'nsleep' from shared library (threads.so) q)sleep peach 00:00:01 00:00:00.100n 0 0i q)psleep[00:00:01 00:00:00.100n;2] 0 0i q)\t sleep peach 00:00:01 00:00:00.100n 1000 q)\t psleep[00:00:01 00:00:00.100n;2] 1000 q)\t sleep peach 00:00:02 00:00:01 00:00:02 00:00:01n // thread 1 has heavier load 4000 q)\t psleep[00:00:02 00:00:01 00:00:02 00:00:01n;2] // same input as previous example but faster due to better load balancing 3001 q)\t sleep peach 00:00:01 00:00:01 00:00:02 00:00:02n 3001 q)\t psleep[00:00:01 00:00:01 00:00:02 00:00:02n;2] // performs about the same as peach for ideal ordering 3002 q)\t sleep peach 20#00:00:01 00:00:02n 20005 q)\t psleep[20#00:00:01 00:00:02n;2] 16007