if I generate Tubes in a loop like here
http://jsfiddle.net/crizzis/RYQty/1/
for (var y = 0; y < 800; y++){...}
The loop is starting to hang and will not finish, despite the main memory seems ok (Task Manager) and the GPU Memory seems to be fine as well.
It hangs in the loop where the tube geometry is generated. It is not even rendered.
Does anyone know how this can happen?
Strange thing is 700 loops are Performing within 5 seconds, 800 loops not at all or really, really slow.
Well, i just looked at your fiddle and i am not sure about your whole loop.
You are creating WAY too much stuff inside your loop. See for example the material. Just create it once outside the loop.
Then move the vector[0] and [1] definitions outside of the loop and inside the loop do vector[0].y = . So you don't create 2 Three.Vector3()-objects for every run. Also, move all variable declarations outside your loop. Just something like var line; and inside, you do line = SPline...
Next, why don't you just create the whole Spline inside the loop and then AFTER the loop, create ONE TubeGeometry afterwards instead of creating hundreds of meshes? Well, I don't know your usecase anyway.
Related
I have been having this issue with p5js on multiple coding projects. Once I have two or more for-loops (they are not nested) in the sketch, nothing will execute AFTER the loop.
I worked around this issue in previous sketches by changing around the order and putting the for-loops last.
However, for my current sketch, I need a for-loop to build on information about arrays in the previous loop. I've even tried adding a simple shape after the loop and before. And the shape will only execute and render on the sketch when it is included BEFORE.
The code for my sketch is quite long but if it will be useful to include it I can.
Thanks for your help.
If the code after a loop is never executed it might mean that your loop never finishes.
I'd recommend using console.log() to debug instead of drawing shapes. This way you can also debug inside the for loop and see if it works correctly.
For example, you can do something like this
console.log("Before loop");
for (let i=0; i<5; i++) {
console.log(`Inside loop. Iteration ${i}`);
}
console.log("After loop");
This code will print
Before loop
Inside loop. Iteration 0
Inside loop. Iteration 1
Inside loop. Iteration 2
Inside loop. Iteration 3
Inside loop. Iteration 4
After loop
As you can see, it's very easy with this code to see that the log before the loop is executed, that the loop executes 5 times and finally the log after the loop is executed.
Put something like this in your code and it will help looking where the code fails.
I'm trying to find a more efficient and speedier way (if possible) to pull subsets of observations that meet certain criteria from multiple hospital claims datasets in SAS. A simplified but common type of data pull would look like this:
data out.qualifying_patients;
set in.state1_2017
in.state1_2018
in.state1_2019
in.state1_2020
in.state2_2017
in.state2_2018
in.state2_2019
in.state2_2020;
array prcode{*} I10_PR1-I10_PR25;
do i=1 to 25;
if prcode{i} in ("0DTJ0ZZ","0DTJ4ZZ") then cohort=1;
end;
if cohort=1 then output;
run;
Now imagine that instead of 2 states and 4 years we have 18 states and 9 years -- each about 1GB in size. The code above works fine but it takes FOREVER to run on our non-optimized server setup. So I'm looking for alternate methods to perform the same task but hopefully at a faster clip.
I've tried including (KEEP=) or (DROP=) statements for each dataset included the SET statement to limit the variables being scanned, but this really didn't have much of an impact on speed -- and, for non-coding-related reasons, we pretty much need to pull all the variables.
I've also experimented a bit with hash tables but it's too much to store in memory so that didn't seem to solve the issue. This also isn't a MERGE issue which seems to be what hash tables excel at.
Any thoughts on other approaches that might help? Every data pull we do contains customized criteria for a given project, but we do these pulls a lot and it seems really inefficient to constantly be processing thru the same datasets over and over but not benefitting from that. Thanks for any help!
I happend to have a 1GB dataset on my compute, I tried several times, it takes SAS no more than 25 seconds to set the dataset 8 times. I think the set statement is too simple and basic to improve its efficient.
I think the issue may located at the do loop. Your program runs do loop 25 times for each record, may assigns to cohort more than once, which is not necessary. You can change it like:
do i=1 to 25 until(cohort=1);
if prcode{i} in ("0DTJ0ZZ","0DTJ4ZZ") then cohort=1;
end;
This can save a lot of do loops.
First, parallelization will help immensely here. Instead of running 1 job, 1 dataset after the next; run one job per state, or one job per year, or whatever makes sense for your dataset size and CPU count. (You don't want more than 1 job per CPU.). If your server has 32 cores, then you can easily run all the jobs you need here - 1 per state, say - and then after that's done, combine the results together.
Look up SAS MP Connect for one way to do multiprocessing, which basically uses rsubmits to submit code to your own machine. You can also do this by using xcmd to literally launch SAS sessions - add a parameter to the SAS program of state, then run 18 of them, have them output their results to a known location with state name or number, and then have your program collect them.
Second, you can optimize the DO loop more - in addition to the suggestions above, you may be able to optimize using pointers. SAS stores character array variables in memory in adjacent spots (assuming they all come from the same place) - see From Obscurity to Utility:
ADDR, PEEK, POKE as DATA Step Programming Tools from Paul Dorfman for more details here. On page 10, he shows the method I describe here; you PEEKC to get the concatenated values and then use INDEXW to find the thing you want.
data want;
set have;
array prcode{*} $8 I10_PR1-I10_PR25;
found = (^^ indexw (peekc (addr(prcode[1]), 200 ), '0DTJ0ZZ')) or
(^^ indexw (peekc (addr(prcode[1]), 200 ), '0DTJ4ZZ'))
;
run;
Something like that should work. It avoids the loop.
You also could, if you want to keep the loop, exit the loop once you run into an empty procedure code. Usually these things don't go all 25, at least in my experience - they're left-filled, so I10_PR1 is always filled, and then some of them - say, 5 or 10 of them - are filled, then I10_PR11 and on are empty; and if you hit an empty one, you're all done for that round. So not just leaving when you hit what you are looking for, but also leaving when you hit an empty, saves you a lot of processing time.
You probably should consider a hardware upgrade or find someone who can tune your server. This paper suggests tips to improve the processing of large datasets.
Your code is pretty straightforward. The only suggestion is to kill the loop as soon as the criteria is met to avoid wasting unnecessary resources.
do i=1 to 25;
if prcode{i} in ("0DTJ0ZZ","0DTJ4ZZ") then do;
output; * cohort criteria met so output the row;
leave; * exit the loop immediately;
end;
end;
I want to change the colour of a part when a player stands on it but instead of putting the script inside the part can i put the script in the workspace and identify the part from an event, like Humanoid touched or something?
The reason is that i have 100's of parts which need to react to a touch event so i don't want to put the same script in each part.
Pseudo-code might be
Player touch part event fired
Identify part from event and change colour of part
Thanks
As M. Ziegenhorn wrote, you could put the script in the character or in the foot directly. That would be the "easiest" way of achieveing this.
However, you could also connect a function to each part easily.
In the code below, we check through a model in workspace named 'TouchParts' which (assumingly) contains the parts you want to tie the touch-function up to.
function Touched(self, Hit)
if Hit and Hit.Parent and Hit.Parent:FindFirstChildOfClass'Humanoid' then
-- We know it's a character (or NPC) since it contains a Humanoid
-- Do your stuff here
print(Hit.Parent.Name, 'hit the brick', self:GetFullName())
self.BrickColor = BrickColor.new('Bright red')
end
end
for _, object in pairs(workspace.TouchParts:GetChildren()) do
if object:IsA'BasePart' then
object.Touched:connect(function(Hit)
Touched(object, Hit)
end)
end
end
Doing it this way means anything in your character touching the part(s) will fire the Touched-event, so you would have to add in a check to see whether if tie part touching is a leg or not.
The pros of binding the function to each part instead of to the leg is that the function is only called when you actually touch one of the intended parts, instead of ANYTHING you touch. However, with an increased amount of parts you connect it to, there's also an increased amount of events which will be triggered and is stored in memory. Probably not noticeable on the scale you're working with, but worth keeping in mind.
Been a while since I coded something on roblox so please excuse any blunders I make.
local parent = workspace.Model --This is the model that contains all of that parts you are checking.
local deb = 5 --Simple debounce variable, it's the minimum wait time in between event fires, in seconds.
local col = BrickColor.new("White") --The color you want to change them to once touched.
for _,object in next,parent:GetChildren() do --Set up an event for each object
if object:IsA("BasePart") then --Make sure it's some sort of part
spawn(function() --Create a new thread for the event so that it can run separately and not yield our code
while true do --Create infinite loop so event can fire multiple times
local hit = object.Touched:wait() --Waits for the object to be touched and assigns what touched it to the variable hit
local player = game.Players:GetPlayerFromCharacter(hit.Parent) --Either finds the player, or nil
if player then --If it was indeed a player that touched it
object.BrickColor = BrickColor.new(col) --Change color; note this is also where any other code that should run on touch should go.
end
wait(deb) --Wait for debounce
end
end)
end
end
This is probably one of the most, if not the most efficient way of doing this.
When a player stands on a block, the value "FloorMaterial" (which is in Humanoid) will be telling you what material the user is standing on, but if the user isn't standing on anything, this value will be nil.
Another efficient method is to use Rays. You would need to create a ray from your HumanoidRootPart.
Example:
IsOnGround=function()
local b=false;
local range=6;
local char=game:service("Players").LocalPlayer.Character;
local root=char:WaitForChild("HumanoidRootPart",1);
if root then
local ray=Ray.new(root.CFrame.p,((root.CFrame*CFrame.new(0,-range,0)).p).unit*range);
local ignore={char};
local hit,pos=workspace:FindPartOnRayWithIgnoreList(ray,ignore,false,false);
pcall(function()
if hit then
b=true;
end
end)
else
print("root not found");
end
return b;
end
This would cast a ray from the HumanoidRootPart, towards the direction where the ground should be, with a distance of 6 studs.
Sadly, this method isn't very effective with R15 characters as far as I know.
My code, as written, works for all the ways I've tested it. I have two questions though. First, Why in the blue blazes do I HAVE to use Do While loops instead of For loops in my code? I've searched Everywhere I can to help me on this issue. I can't reinstall excel, but I've reset as many of the settings as I can, but, invariably, the compiler skips over every for loop I have that isn't a for each loop... Except the first for loop in my programming... It is the weirdest and most bizarre behavior I have ever seen. I have used step through (F8) 10000 times to try and figure out why it keeps skipping. But every single time i make a for loop, it doesn't even run the first line of it.
To be clear, every place I have a Do While ... Loop, it SHOULD be a For Next. But making this change breaks the code every time because every spot the do while is changed to for, the code is skipped entirely. Even if I reset the i value to 0. The issue happens even if I have a different iterator for each loop.
Running w8 on an Intel i5 with Office 2010.
For i=1 To i = 100
If (i >= startRow And i <= stopRow And Not rowDone(i) And Not i = colFocus) Then
colCurPayAmounts(i) = S_Debt.Cells(i, 5)
Else
colCurPayAmounts(i) = 0
End If i = i + 1
Next i
The problem is it should be For i = 1 To 100 and not For i = 1 To i = 100 #Rory
Assume I have a function which is called often, say by an ODE-solver or similar. Is it faster to use a persistent variable than to reallocate it each time?
That is, which function would be faster and what is best practice?
function ret=thisfunction(a,b,c)
A = zeros(3)
foo = 3;
bar = 34;
% ...
% process some in A
% ...
ret = A\c;
end
or
function ret=thatfunction(a,b,c)
persistent A foo bar
if isempty(A);
A=zeros(3);
foo = 3;
bar = 34;
end
% ...
% process some in A
% ...
ret = A\c;
end
Which one is faster can only be proven by test, as it may depend on variable size etc. However, I would say that if it is not required, it is usually also not recommended to use persistent variables.
Therefore I would definately recommend you to use option number one.
Sidenote: You probably want to check whether it exists rather than whether it is empty. Furthermore I don't know what happens to your A when you leave the function scope, if you want to define it as persistent or global you may have to do it one level higher.
When you have a single function such as this to test I have found that it's very easy to setup a parent function, run the function you are testing say, 10 million times and time the results. Then consider the difference in time AND the possible trade off or side effects of using a persistent variable here. It may not be worth it if the difference is a few percent over 10 million calls and you are actually only going to call the function 10 thousand times in application. YMMV.
In regards to best practice, I would dissuade you from using persitent variables in this manner, for two reasons.
Persitent variables can be cleared externally, e.g. running clear('thatfunction') from any other function that has "thatfunction" on the path would reset your persitent variables in "thatfunction". As such, it's possible that they'll be unwittingly reset elsewhere. This may not be a problem for you in this context, but if you want to keep results between function calls (which is the primary point of persitent variables) this can cause you headaches.
Also, if you modify them, you'll have to remember to clear them when you're done running in-order to reset your workspace to a clean state. Otherwise if you (or someone else) runs your program again without clearing your persitent variable(s) first, the results from the previous run. This isn't an issue if they're read-only, but you cannot enforce that they will be.