Why does Julia run a function faster than the non-function equivalent? - julia

So, today I decided to try Julia and I came across something odd I couldn't quite understand the reason for nor find a decent answer to with my search queries so here I am...
First, I wanted to have something to benchmark Python against, I settled for this very simple piece of code.
def test():
start = time()
a = 1
while a < 10000000:
a+=1
print(time() - start)
This took ~0.9s to execute in Python 3.3 on my machine. Then I ran the following in Julia.
start = time()
a = 1
while a < 10000000
a+=1
end
print(time() - start)
It took ~0.7s to execute. So I concluded that simple arithmetic performance in Julia is ~= to Python.
However, when I made it into a function, I stumbled upon the weirdness I wasn't expecting which turned my result on its head.
function test_arithmetic()
start = time()
a = 1
while a < 10000000
a+=1
end
print(time() - start)
end
test_arithmetic()
This codesnippet took only ~0.1s to execute, why is this?

The reason is that a global variable can have its type changed at any point, which makes it hard for the compiler to optimize. This is mentioned in the Performance Tips section of the manual.

I found the answer, it has to do with how it is faster to store local variables compared to globals.
The equivalent question for Python (which led me to test if the same applied to Julia) can be found here.
It turns out that this code-snippet runs in ~0.7s as well.
function test_arithmetic()
start = time()
global a = 1
while a < 10000000
a+=1
end
print(time() - start)
end
test_arithmetic()

Related

How can I test whether stdin has input available in julia?

I would like to detect whether there is input on stdin in a short time window, and continue execution either way, with the outcome stored in a Bool. (My real goal is to implement a pause button on a simulation that runs in the terminal. A second keypress should unpause the program, and it should continue executing.) I have tried to use poll_fd but it does not work on stdin:
julia> FileWatching.poll_fd(stdin, readable=true)
ERROR: MethodError: no method matching poll_fd(::Base.TTY; readable=true)
Is there a way that will work on julia? I have found a solution that works in python, and I have considered using this via PyCall, but I am looking for
a cleaner, pure-julia way; and
a way that does not fight or potentially interfere with julia's use of libuv.
bytesavailable(stdin)
Here is a sample usage. Note that if you capture the keyboard you also need to handle Ctrl+C yourself (in this example only the first byte of chunk is checked).
If you want to run it fully asynchronously put #async in front of the while loop. However if there will be no more code in this case this program will just exit.
import REPL
term = REPL.Terminals.TTYTerminal("xterm",stdin,stdout,stderr)
REPL.Terminals.raw!(term,true)
Base.start_reading(stdin)
while (true)
sleep(1)
bb = bytesavailable(stdin)
if bb > 0
data = read(stdin, bb)
if data[1] == UInt(3)
println("Ctrl+C - exiting")
exit()
end
println("Got $bb bytes: $(string(data))")
end
end
Following #Przemyslaw Szufel's response, here is a full solution that allows a keypress to pause/unpause the iteration of a loop:
import REPL
term = REPL.Terminals.TTYTerminal("xterm",stdin,stdout,stderr)
REPL.Terminals.raw!(term,true)
Base.start_reading(stdin)
function read_and_handle_control_c()
b = bytesavailable(stdin)
#assert b > 0
data = read(stdin, b)
if data[1] == UInt(3)
println("Ctrl+C - exiting")
exit()
end
nothing
end
function check_for_and_handle_pause()
if bytesavailable(stdin) > 0
read_and_handle_control_c()
while bytesavailable(stdin) == 0
sleep(0.1)
end
read_and_handle_control_c()
end
nothing
end
while true
# [do stuff]
sleep(0.05)
check_for_and_handle_pause()
end
This is somewhat suboptimal in that it requires the process to wake up regularly even when paused, but it achieves my goal nevertheless.

Scope of for loops in julia [duplicate]

This snippet of code is from JuliaBoxTutorials
myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
i = 1;
while i <= length(myfriends)
friend = myfriends[i]
println("Hi $friend, it's great to see you!")
i += 1
end
giving this error when run with Julia v1.0
UndefVarError: i not defined
Stacktrace:
[1] top-level scope at ./In[12]:5 [inlined]
[2] top-level scope at ./none:0
But when i += 1 is replaced with global i += 1 it works. I guess this was still working in v0.6 and the tutorial will be adapted once the new Intro to Julia is published this Friday.
I was just wondering, is it possible, to make a while loop without stating a global variable?
As #Michael Paul and #crstnbr already replied in the comments, the scoping rules have been changed (Scope of variables in Julia). The for and while loop introduce a new scope and have no access to the outside (global) variables. You can get scope access using the global keyword but the recommended workflow is wrapping your code in functions.
One of the benefits of the new design is that the user is forced to avoid such global constructs which directly affect the performance of functions - which cannot be type stable when they access global variables.
One downside is the confusion when experimenting in the REPL and seeing such errors.
In my opinion the new behaviour is the cleaner one with respect to predictability. It was however a very tough and long-running discussion within the whole Julia community ;)
There is currently a discussion if the REPL will be changed to behave like the old one by making use of let-wraps: https://github.com/JuliaLang/julia/issues/28789
This is something which is not practical to be done manually (much more complicated then using the global keyword), see the example by Stefan Karpinski: https://github.com/JuliaLang/julia/issues/28789#issuecomment-414666648
Anyways, for the sake of completeness (although I would not recommend doing this) here is a version using global:
myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
i = 1;
N = length(myfriends)
while i <= N # you cannot even call a function here
# with a global, like length(myfriends)
global i, myfriends
friend = myfriends[i]
println("Hi $friend, it's great to see you!")
i += 1
end
Note however that this is also completely valid:
myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
greet(friend) = println("Hi $friend, it's great to see you!")
for friend in myfriends
greet(friend)
end
I found that this works in Julia v1.0:
let
myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
i = 1;
while i <= length(myfriends) # this function here seems to work no problem
friend = myfriends[i]
println("Hi $friend, it's great to see you!")
i = i + 1 # gives syntax error when prefixed with global
end
end
In fact, it will give me a syntax error if I try to make i global :) within the while loop.

Monitoring files for modifications

I’m trying to write a simple code that continuously checks when files in a given folder are modified and, upon modification, triggers a function.
I've added a MWE below, it "works" but I was wondering if
there are libraries or utilities that I should look into that help for such a problem?
there was a cleaner way to have something running continuously until some event (here an interruption)
files_and_times = Dict{String, Int}()
for (root, _, files) ∈ walkdir(dirpath)
for f ∈ files
fpath = joinpath(root, f)
files_and_times[fpath] = stat(fpath).mtime
end
end
try
while true
for (f, t) ∈ files_and_times
cur_t = stat(f).mtime
if cur_t > t
files_and_times[f] = cur_t
println("file $f was modified")
end
end
sleep(0.5)
end
catch x
if isa(x, InterruptException)
println("Shutting down.")
else
throw(x)
end
end
The comments by #rickhg12hs and #Colin_T_Bowers effectively answer my question. Posting an answer to close the question.
FileWatching seems to be precisely what I was looking for,
The package Revise seems to have good examples showing how to use it and,
this discourse thread discusses limitations.

Exact usage of Async.Sleep() in F#

I have a question:
I have problem in usage Async.Sleep() method in F#. This is a piece of code in my program:
if (newAngle <> currentAngle) then
if (newAngle = 0) then
Motor(MotorPort.OutA).SetSpeed(100y)
angle1 <- Motor(MotorPort.OutA).GetTachoCount()
**Async.Sleep(20)**
angle2 <- Motor(MotorPort.OutA).GetTachoCount()
speed <- abs(angle2 - angle1)
distance <- abs(newAngle - angle2)
if (speed > 11) then
pwr <- 20L + int64 distance
if (pwr < 100L) then
Motor(MotorPort.OutA).SetSpeed(sbyte pwr)
while (distance > 30 || angle2 <> angle1) do
angle1 <- Motor(MotorPort.OutA).GetTachoCount()
**Async.Sleep(20)**
angle2 <- Motor(MotorPort.OutA).GetTachoCount()
speed <- abs(angle2 - angle1)
distance <- abs(newAngle - angle2)
if (speed > 11) then
pwr <- 20L + int64 distance
if (pwr < 100L) then
Motor(MotorPort.OutA).SetSpeed(sbyte pwr)
Motor(MotorPort.OutA).Off() //? off
**Async.Sleep(300)**
I have used Async.Sleep() function in some places in my code. But unfortunately, when I use Async.Sleep() method I get this error:
This expression was expected to have type unitbut here has type Async<unit>
How can I solve this problem?
You need a do! before the call to Async.Sleep, i.e.
async{
...
do! Async.Sleep(time * 1000)
...
}
How to research this on your own next time:
Bing "Async.Sleep"
First result - MSDN docs for F# Async.Sleep
Look at example code.
Async.sleep gives back some "async" code.
The "async" computation expression builder allows to inject computations to a new type, async<_>, and weave such computations in a way which does not block a single thread, by relying on the threadpool and knowing how to suspend (and resume !) computations in a efficient way.
The bottom line is that the main benefit is the controlled weaving (and - different aspect - controled execution) of such computations.
If you just need one Async instruction, there is no weaving, and no benefit in using the async<_> type. As suggested, you propably want to use the Thread.Sleep
The best way to learn about those async is to unsugar the async computation expression into its succession of callback. every computation expression is compiled to that form.
Then you can look at the specific operations invoked, which are specific to the async computation expression builder.
--
Unfortunately, while F# async make everything possible to make it simple to use, such feature is nonetheless not trivial, and require some time to understand.
I suggest you look at it as a subject on its own first, and not go for a quick fix.
The good part is that it is quite instructive to understand this technique as it uses more general mechanism like computation expression !
Async.Sleep returns an async computation. All you have to do is just run it and wait until it finishes:
Async.Sleep(5000) |> Async.RunSynchronously
Try the following:
open System.Threading
//and wherever requires write the below mentioned code
Thread.Sleep(20000) //20000 in Milliseconds unit

Detecting keystrokes in Julia

I have a piece of code in Julia in which a solver iterates many, many times as it seeks a solution to a very complex problem. At present, I have to provide a number of iterations for the code to do, set low enough that I don't have to wait hours for the code to halt in order to save the current state, but high enough that I don't have to keep activating the code every 5 minutes.
Is there a way, with the current state of Julia (0.2), to detect a keystroke instructing the code to either end without saving (in case of problems) or end with saving? I require a method such that the code will continue unimpeded unless such a keystroke event has happened, and that will interrupt on any iteration.
Essentially, I'm looking for a command that will read in a keystroke if a keystroke has occurred (while the terminal that Julia is running in has focus), and run certain code if the keystroke was a specific key. Is this possible?
Note: I'm running julia via xfce4-terminal on Xubuntu, in case that affects the required command.
You can you an asynchronous task to read from STDIN, blocking until something is available to read. In your main computation task, when you are ready to check for input, you can call yield() to lend a few cycles to the read task, and check a global to see if anything was read. For example:
input = ""
#async while true
global input = readavailable(STDIN)
end
for i = 1:10^6 # some long-running computation
if isempty(input)
yield()
else
println("GOT INPUT: ", input)
global input = ""
end
# do some other work here
end
Note that, since this is cooperative multithreading, there are no race conditions.
You may be able to achieve this by sending an interrupt (Ctrl+C). This should work from the REPL without any changes to your code – if you want to implement saving you'll have to handle the resulting InterruptException and prompt the user.
I had some trouble with the answer from steven-g-johnson, and ended up using a Channel to communicate between tasks:
function kbtest()
# allow 'q' pressed on the keyboard to break the loop
quitChannel = Channel(10)
#async while true
kb_input = readline(stdin)
if contains(lowercase(kb_input), "q")
put!(quitChannel, 1)
break
end
end
start_time = time()
while (time() - start_time) < 10
if isready(quitChannel)
break
end
println("in loop # $(time() - start_time)")
sleep(1)
end
println("out of loop # $(time() - start_time)")
end
This requires pressing and then , which works well for my needs.

Resources