I am currently trying to constantly check a condition inside an infinite while loop. I am breaking out of the loop with a few conditionals. However, the while loop is immediately breaking and a debugging println() shows that the code is inside of the first if() statement. Hoover, the preceding line was never run and the if statement needs that information (polar) to compute. I only get an error when trying to call polar later in the program and it does not exist. It is as if that line has been entirely skipped.
Here is the while loop in question:
prevSize = 0
sec = 0
n = 5
while true # wait unit the polar file is done changing
polar = readdlm(polarPath,Float64,skipstart = 12)
if polar[end,1] > aEnd - aStep
println("Done writing polar file")
break #File is fully loaded
else #check every n seconds for stable file size
sleep(1)
global sec += 1
if prevSize == filesize(polarPath) && sec == n
println("Polar file could not converge for all AoA")
break # after n seconds if filesize is constant then use current polar
elseif sec >= n
global sec = 0 # reset sec every n seconds
end
global prevSize = filesize(polarPath)
end
end
The program prints out "Done writing polar file" which means that it used the first break. However, polar was never initialized as a variable and separately calling polar[end,1] > aEnd - aStep gives the expected error of no variable called polar. So my question is how can the code have skipped over the line defining polar and then evaluated an if statement that it does not have the information for?
Here is a simple example of how scoping rules work when using a while loop.
First example, using while inside main:
julia> outvar = 5
5
julia> invar = 5
5
julia> while true
global outvar
invar = outvar
outvar += 1
if outvar > 10
break
end
end
julia> outvar
11
julia> invar
5
So I defined both outvar and invar outside of the while loop, accessed the outvar variable outside the scope while by calling global outvar so the loop works and it does update outvar. But our invar variable is still set to 5, as the variable invar inside the while loop is not connected to the outside the while loop - it lives in its own tiny universe.
An easy way to fix this is to create a function:
function add_nums(outvar)
invar = outvar
while true
invar = outvar
outvar += 1
if outvar > 10
break
end
end
return invar
end
This takes an outvar, defines invar outside the while loop so that you can add additional logic here if you wanted to and the executes the loop and returns your new invar.
Once you have this function you can achieve the goal of the original while loop easily:
julia> outvar = 5
5
julia> invar = add_nums(outvar)
10
Even better, your outvar variable is affected by these function calls:
julia> outvar
5
I hope the above example helps you achieve what you want. You just need to create a function that implements your file loading logic.
Related
I am making a Roblox game and I want it to have a stopwatch. The stopwatch works, but it counts very slowly for some reason.
Here's my ScreenGui in StarterGui:
Here's the code inside the LocalScript:
local timer = script.Parent.Timer
local tms = 00
local ts = 00
local tm = 00
local tt
local tts
local y = 0
local whichtower = game.Players.LocalPlayer:FindFirstChild("WhichTower")
while true do
wait(0.01)
if whichtower.Value == "" then
tms = 00
ts = 00
tm = 00
tts = 0
else
tms = tms + 1
if tms == 100 then
ts = ts + 1
tms = 0
tts = tts + 1
if ts == 60 then
tm = tm + 1
ts = 0
end
end
tt = tostring(tm)..":"..tostring(ts)..":"..tostring(tms)
timer.Text = tt
game.Players.LocalPlayer:FindFirstChild("Time").Value = tt
end
end
The arbitrary wait() and loop is a possible cause of timing issues, although I can't see anything specific that might be slowing it down. Are you sure that :FindFirstChild on WHichTower is always returning results? Add a print statement there, so your debug window has a constant stream of values, and you can confirm if it's finding a suitable tower.
Also, you are only updating the text if there's a Tower; for the code where you set the values to 0, there's no timer.Text update.
But if you don't think that's the issue:
I'd try put your code in a Heartbeat function, called regularly and tied to the refresh rate (I think). Then you don't need the while loop, nor the wait() commands. The Heartbeat only runs as fast as the refresh rate, therefore, there's no point trying to running anything quicker than that because the screen won't update.
local lPlayers = game:GetService("Players")
local lRunSvc = game:GetService("RunService")
local function onPlayerAdded(pPlayer) -- pPlayer (variable name is up to you) is the ref to the joined player.
print(pPlayer.Name .. " joined the game.")
lRunSvc.Heartbeat:Connect(function()
print("whichtower.value is:" .. whichtower.Value) -- View prints in the Output console
if whichtower.Value == "" then
tms = 00
ts = 00
tm = 00
tts = 0
else
tms = tms + 1
if tms == 100 then
ts = ts + 1
tms = 0
tts = tts + 1
if ts == 60 then
tm = tm + 1
ts = 0
end
end
tt = tostring(tm)..":"..tostring(ts)..":"..tostring(tms)
timer.Text = tt
game.Players.LocalPlayer:FindFirstChild("Time").Value = tt
end
end)
end
lPlayers.PlayerAdded:Connect(onPlayerAdded) -- This is called when a player joins
Just as Vexen Crabtree has pointed out, the time that wait() will actually pause a script is based on a system clock's best guess of how much time has passed. Rather than counting up the milliseconds, a more reliable method for calculating passed time is to use the tick() function.
tick() will give you the current epoch time, which is the number of milliseconds that have passed since January 1st, 1970.
So, if you know a starting time, you can subtract it from the current time and get the number of milliseconds that have passed. This method doesn't rely on loop timings and will give a more accurate measure of the actual time that has passed. The amount of time that you chose with wait() will only reflect the speed at which the value will be updated.
local timer = script.Parent.Timer
local whichtower = game.Players.LocalPlayer:FindFirstChild("WhichTower")
local playerTime = game.Players.LocalPlayer:FindFirstChild("Time")
local startingTime = 0
local isTiming = false
-- attach a listener to know when to start the clock
whichTower.Changed:Connect(function(newValue)
-- reset the clock to zero when the value is empty
isTiming = newValue ~= ""
if not isTiming then
startingTime = 0
else
-- start the clock!
startingTime = tick()
end
end)
local refreshTime = 0.01
while true do
wait(refreshTime)
if isTiming then
-- calculate the time that has passed
local ms = tick() - startingTime
-- calculate how many minutes have passed
local tm = ms - (ms % (60 * 1000))
ms = ms - tm
tm = tm / 1000
-- calculate how many seconds have passed
local ts = ms - (ms % 1000)
ms = ms - ts
ts = ts / 1000
-- format the remainder
local tms = ms / 1000
if #tostring(tms) > 2 then
tms = string.sub(tostring(tms), 3)
else
tms = "0"
end
-- format the time into mm:ss.ss ex) 123:01.123
local tt = string.format("%.2d:%.2d.%s", tm, ts, tms)
timer.Text = tt
playerTime.Value = tt
end
end
I have figured it out using a different set of code. Roblox limits the wait parameters to a minimum of 0.03 seconds, so that is why my previous code was not working.
I have a parallel region in my fortran code that uses OpenMP and calls subroutines that use variables with the save attribute in their scope. This is causing a problem because they are shared between threads, so my question is if there is a way to make these variables private while still being saved between subroutine calls, or will I need to input and output them?
Thanks
You can do it using threadprivate - the code below shows a couple of slightly different approaches. But please note
a) The values are only guaranteed to be preserved between parallel regions if the parallel regions use the same number of threads
b) Please think carefully whether you really need save, save and parallel programming are very rarely good bed fellows. There are one or two good uses (see e.g. Fortran OpenMP with subroutines and functions), but if there is an alternative way to do what you want to do (e.g. passing through the argument list) this will almost certainly cause you less pain in the long run
(For some reason using a proper list breaks the formatting of the code below - if someone knows how to fix that, thanks!)
ian#eris:~/work/stack$ cat threadprivate.f90
Program test
Implicit None
Call do_something
Call do_something
Call do_something
Write( *, * )
!$omp parallel
Call do_something_else
Call do_something_else
Call do_something_else
!$omp end parallel
Contains
Subroutine do_something
Use omp_lib
Implicit None
Integer, Save :: calls = 0
Integer, Save :: stuff
Logical, Save :: first = .True.
!$omp threadprivate( first, stuff )
calls = calls + 1
! Shouldn't scope threadprivate variables - they are already private
!$omp parallel default( none ) shared( calls )
If( first ) Then
first = .False.
stuff = omp_get_thread_num()
Else
stuff = stuff + 1
End If
Write( *, '( 3( a, 1x, i2, 1x ) )' ) 'do something call ', calls, &
'thread = ', omp_get_thread_num(), 'stuff = ', stuff
!$omp end parallel
End Subroutine do_something
Subroutine do_something_else
Use omp_lib
Implicit None
Integer, Save :: calls = 0
Integer, Save :: stuff
Logical, Save :: first = .True.
!$omp threadprivate( first, stuff, calls )
calls = calls + 1
If( first ) Then
first = .False.
stuff = omp_get_thread_num()
Else
stuff = stuff + 1
End If
Write( *, '( 3( a, 1x, i2, 1x ) )' ) 'do something else call ', calls, &
'thread = ', omp_get_thread_num(), 'stuff = ', stuff
End Subroutine do_something_else
End Program test
ian#eris:~/work/stack$ gfortran -std=f2008 -Wall -Wextra -O -g -fcheck=all -pedantic -fopenmp threadprivate.f90
ian#eris:~/work/stack$ export OMP_NUM_THREADS=2
ian#eris:~/work/stack$ ./a.out
do something call 1 thread = 0 stuff = 0
do something call 1 thread = 1 stuff = 1
do something call 2 thread = 1 stuff = 2
do something call 2 thread = 0 stuff = 1
do something call 3 thread = 1 stuff = 3
do something call 3 thread = 0 stuff = 2
do something else call 1 thread = 1 stuff = 1
do something else call 2 thread = 1 stuff = 2
do something else call 3 thread = 1 stuff = 3
do something else call 1 thread = 0 stuff = 0
do something else call 2 thread = 0 stuff = 1
do something else call 3 thread = 0 stuff = 2
ian#eris:~/work/stack$ export OMP_NUM_THREADS=4
ian#eris:~/work/stack$ ./a.out
do something call 1 thread = 3 stuff = 3
do something call 1 thread = 2 stuff = 2
do something call 1 thread = 1 stuff = 1
do something call 1 thread = 0 stuff = 0
do something call 2 thread = 1 stuff = 2
do something call 2 thread = 3 stuff = 4
do something call 2 thread = 0 stuff = 1
do something call 2 thread = 2 stuff = 3
do something call 3 thread = 3 stuff = 5
do something call 3 thread = 1 stuff = 3
do something call 3 thread = 0 stuff = 2
do something call 3 thread = 2 stuff = 4
do something else call 1 thread = 3 stuff = 3
do something else call 2 thread = 3 stuff = 4
do something else call 3 thread = 3 stuff = 5
do something else call 1 thread = 1 stuff = 1
do something else call 2 thread = 1 stuff = 2
do something else call 3 thread = 1 stuff = 3
do something else call 1 thread = 0 stuff = 0
do something else call 2 thread = 0 stuff = 1
do something else call 3 thread = 0 stuff = 2
do something else call 1 thread = 2 stuff = 2
do something else call 2 thread = 2 stuff = 3
do something else call 3 thread = 2 stuff = 4
ian#eris:~/work/stack$
This question already has answers here:
for loop missing initialization
(6 answers)
Closed 3 years ago.
I'm new to CS, and found this code online. What does this blank between two semicolons indicate? What's the range of this for loop? Thanks.
for (int i = 0, temp; ; i++)
This is the typical structure of a for loop:
for(initialization; condition ; increment/decrement)
{
statement(s);
}
but yours is as follows:
for(initialization; ; increment)
{
statement(s);
}
As you can see the condition part is removed which is completely valid, but this just means that the loop will run infinitely.
Typically in cases like this, some logic inside the loop block will be responsible to break out of the loop given some condition is met.
If you look at the reference for for at learn.microsoft.com you can see the following example.
The following example defines the infinite for loop:
for ( ; ; )
{
// Body of the loop.
}
The infinity comes from the "the condition section" being empty. Again from the reference:
The condition section, if present, must be a boolean expression. That expression is evaluated before every loop iteration. If the condition section is not present or the boolean expression evaluates to true, the next loop iteration is executed; otherwise, the loop is exited.
Here's a bad clock implemented via a never-ending loop to show the difference between how i and temp change as the loop progresses.
public async static Task Main(string[] args)
{
var start = DateTime.Now;
for (int i = 0, temp; ; i++)
{
// 'i' is a) initalised and b) incremented after each
// 'temp' is a) *un*initialised and b) doesn't automatically change
temp = 666;
Console.WriteLine($"It's now {DateTime.Now.TimeOfDay} and this is about {i} seconds after {start.TimeOfDay}. 'temp' is {temp}");
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
Output:
It's now 09:07:02.9269857 and this is about 0 seconds after 09:07:02.9246017. 'temp' is 666
It's now 09:07:04.0195240 and this is about 1 seconds after 09:07:02.9246017. 'temp' is 666
It's now 09:07:05.0223953 and this is about 2 seconds after 09:07:02.9246017. 'temp' is 666
It's now 09:07:06.0379706 and this is about 3 seconds after 09:07:02.9246017. 'temp' is 666
It's now 09:07:07.0482980 and this is about 4 seconds after 09:07:02.9246017. 'temp' is 666
See the docs for for:
The for statement defines initializer, condition, and iterator sections:
for (initializer; condition; iterator)
body
All three sections are optional.
Also, from the same source:
If the condition section is not present or the boolean expression evaluates to true, the next loop iteration is executed; otherwise, the loop is exited.
(emphasis mine)
I have the following Julia function which takes an input array and distributes it among available workers.
function DistributeArray(IN::Array,IN_symb::Symbol;mod=Main) # Distributes an array among workers
dim = length(size(IN))
size_per_worker = floor(Int,size(IN,1) / nworkers())
StartIdx = 1
EndIdx = size_per_worker
for (idx, pid) in enumerate(workers())
if idx == nworkers()
EndIdx = size(IN,1)
end
if dim == 3
#spawnat(pid, eval(mod, Expr(:(=), IN_symb, IN[StartIdx:EndIdx,:,:])))
elseif dim == 2
#spawnat(pid, eval(mod, Expr(:(=), IN_symb, IN[StartIdx:EndIdx,:])))
elseif dim == 1
#spawnat(pid, eval(mod, Expr(:(=), IN_symb, IN[StartIdx:EndIdx])))
else
error("Invalid dimensions for input array.")
end
StartIdx = EndIdx + 1
EndIdx = EndIdx + size_per_worker - 1
end
end
I call this function inside some of my other functions to distribute an array. As an example, here is a test function:
function test(IN::Array,IN_symb::Symbol)
DistributeArray(IN,IN_symb)
#everywhere begin
if myid() != 1
println(size(IN))
end
end
end
I expect this function to take the 'IN' array and distribute it among all available workers, then print the size allocated to each worker. The following set of commands (where the names of the inputs match the names used inside the functions) works correctly:
addprocs(3)
IN = rand(27,33)
IN_symb = :IN
test(IN,IN_symb)
# From worker 2: (9,33)
# From worker 3: (8,33)
# From worker 4: (10,33)
However, when I change the names of the inputs so that they are different from the names used in the functions, I get an error (start a new julia session before running the follow commands):
addprocs(3)
a = rand(27,33)
a_symb = :a
test(a,a_symb)
ERROR: On worker 2:
UndefVarError: IN not defined
in eval at ./sysimg.jl:14
in anonymous at multi.jl:1378
in anonymous at multi.jl:907
in run_work_thunk at multi.jl:645
[inlined code] from multi.jl:907
in anonymous at task.jl:63
in remotecall_fetch at multi.jl:731
in remotecall_fetch at multi.jl:734
in anonymous at multi.jl:1380
...and 3 other exceptions.
in sync_end at ./task.jl:413
[inlined code] from multi.jl:1389
in test at none:2
I don't understand what is causing this error. It appears to me that the functions are not using the inputs that I give them?
In your function test() you are running println(size(IN)). Thus, you are looking on each of the processes for a specific object named IN. In the second example, however, you are naming your objects a rather than IN (since the symbol you supply is :a). The symbol that you supply to the DistributeArray() function is what defines the name that the objects will have on the workers, so that is the name you use to refer to those objects in the future.
You could achieve the results that I think you're looking for, though, with a slight modification to your test() function:
function test(IN::Array,IN_symb::Symbol)
DistributeArray(IN,IN_symb)
for (idx, pid) in enumerate(workers())
#spawnat pid println(size(eval(IN_symb)))
end
end
In my opinion, #spawnat can be a bit more flexible at times in letting you better specify the expressions you want it to evaluate.
Hello I've been trying to get this code to work, I even cheated and added in the goal to my code and its still not accepting my answer, any suggestions?
-- Functions...
function p() -- For user imput..
print("Enter # and try to get the closest to it! (Valid range is 1-100)")
local var = tonumber(io.read())
if var == nil then
var = 0
end
return var
end
--Start main code..
-- Initialize the pseudo random number generator (I'm on windows...)
math.randomseed( os.time() )
math.random(); math.random(); math.random()
-- Setting goal
goal = math.random(1,100)
-- Guessing loop...
repeat
g = p()
print(g)
print(goal)
until g == Goal
print("YOU GUESSED THE GOAL!")
Replace the G by a lower case g.
until g == goal