Slow performance on passing large hash by reference to subroutine - arrays

This code
foreach my $ti (#forward){
my $new_bs = %blast_values->{ $ti }->{"bitscore"};
if($new_bs > $fbs){
$fti = $ti;
$fbs = $new_bs;
}
}
my $fqstart = %blast_values->{ $fti }->{"qstart"};
my $fqend = %blast_values->{ $fti }->{"qend"};
my $fsstart = %blast_values->{ $fti }->{"sstart"};
my $fsend = %blast_values->{ $fti }->{"send"};
was originally done with a subroutine call:
my ($fti, $fqstart, $fqend, $fsstart, $fsend, $fbs) = best_one(\#forward,\%blast_values);
where inside the subroutine it did:
my #forward = #{$_[0]};
my %blast_values = %{$_[1]};
However, the subroutine version ran about 40X slower than did the code shown at the top of this post. The subroutine version was the same code, just moved into the subroutine and then return the scalar values indicated. The subroutine would have been called about 30K times if I had let it run to completion, which I never did, because it was going to take about 1800 seconds. Place debug output line before the "foreach" in the subroutine and there was a noticeable delay between output lines during a run, on the order of 1 second, whereas for the version in the main part of the perl there is no measurable delay (so < 0.1 seconds or so between output lines).
The array was generally very small, with 1 or 2 (99% of the time) entries and rarely up to 12. The hash, on the other hand, was very, very large. It has something like 1.5M keys and each key has 6 values accessed by subkeys. Both are passed by reference, so the size of their contents really should not have mattered.
What might account for this delay? I do not recall there being this much call overhead on Perl subroutine invocations, and the input parameters are passed by reference, so it isn't like it had to copy the huge hash. (Although the execution speed suggests maybe it was doing so.)
Perl 5.8.8 on Centos 5.

It's slow because when you do this
my #forward = #{$_[0]};
my %blast_values = %{$_[1]};
You are dereferencing the references you passed in and copying the referenced structures into new variables. If %blast_values is very big, that's a lot of work.
Instead, just use the references without copying. (That's what they're for.)
my $forward = shift;
my $blast_values = shift;
my $fqstart = $blast_values->{ $fti }->{"qstart"};
# etc
Also, I assume you're aware that %blast_values->{ $fti }->{"qstart"} doesn't make sense. The fact that it works at all is due to a bug in Perl. Using such a construct has issued a warning ("Using a hash as a reference is deprecated") for years. You should have been using $blast_values{ $fti }->{"qstart"}.

Related

Reordering array dimensions in matlab

First, some background:
As part of a much larger code I'm reading in data from a netCDF input file. I produce this input file beforehand. The code has been written to expect a term F which is an array shaped like t-by-x-by-y-by-z where time t usually has around 20 values, and x and y dimensions are usually of the order 1000 entries each and z has usually about 5.
In summary, F is a 20x1000x1000x5 array.
This format is incredibly slow to read. It is many times faster to read it if it's written in the format x-by-y-by-z-by-t.
So what instead I am now producing an input netCDF file containing Fnew, which is a 1000x1000x5x20 array.
Now my question: I want to make as few changes to the larger code as possible, so after Fnew is read in, I immediately want to rearrange it to match F.
There must be an easy solution to this?
As Cris Luengo commented, the permute function is what you need. This is how you would use it in your context:
function test()
%% instead of the current (using 10 instead of 1000 just for demo purposes):
txyz = rand(20,10,10,5);
largerCodeOld(txyz);
%% you can now use:
xyzt = rand(10,10,5,20);
largerCodeNew( xyzt );
end
function largerCodeOld(txyz)
% do stuff with txyz
end
function largerCodeNew(xyzt)
txyz = permute(xyzt,[ 4, 1:3 ]);
% either do stuff with txyz
% or call largerCodeOld( txyz )
end

Updating a static array, in a nested function without making a temporary array? <Julia>

I have been banging my head against a wall trying to use static arrays in julia.
https://github.com/JuliaArrays/StaticArrays.jl
They are fast but updating them is a pain. This is no surprise, they are meant to be immutable!
But it is continuously recommended to me that I use static arrays even though I have to update them. In my case, the static arrays are small, just length 3, and i have a vector of them, but I only update 1 length three SVector at a time.
Option 1
There is a really neat package called Setfield that allows you to do inplace updates of SVectors in Julia.
https://github.com/jw3126/Setfield.jl
The catch... it updates the local copy. So if you are in a nested function, it updates the local copy. So it comes with some book keeping since you have to inplace update the local copy and then return that copy and update the actual array of interest. You can't pass in your desired array and update it in place, at least, not that I can figure out! Now, I do not mind bookeeping, but I feel like updating a local copy, then returning the value, updating another local copy, and then returning the values and finally updating the actual array must come with a speed penalty. I could be wrong.
Option 2
It bugs me that in order to do an update a static array I must
exampleSVector::SVector{3,Float64} <-- just to make clear its type and size
exampleSVector = [value1, value2, value3]
This will update the desired array even if it is inside a function, which is nice and the goal, but if you do this inside a function it creates a temporary array. And this kills me because my function is in a loop that gets called 4+ million times, so this creates a ton of allocations and slows things down.
How do I update an SVector for the Option 2 scenario without creating a temporary array?
For the Option 1 scenario, can I update the actual array of interest rather than the local copy?
If this requires a simple example code, please say so in the comments, and I will make one. My thinking is that it is answerable without one, but I will make one if it is needed.
EDIT:
MCVE code - Option 1 works, option 2 does not.
using Setfield
using StaticArrays
struct Keep
dreaming::Vector{SVector{3,Float64}}
end
function INNER!(vec::SVector{3,Float64},pre::SVector{3,Float64})
# pretend series of calculations
for i = 1:3 # illustrate use of Setfield (used in real code for this)
pre = #set pre[i] = rand() * i * 1000
end
# more pretend calculations
x = 25.0 # assume more calculations equals x
################## OPTION 1 ########################
vec = #set vec = x * [ pre[1], pre[2], pre[3] ] # UNCOMMENT FOR FOR OPTION 1
return vec # UNCOMMENT FOR FOR OPTION 1
################## OPTION 2 ########################
#vec = x * [ pre[1], pre[2], pre[3] ] # UNCOMMENT FOR FOR OPTION 2
#nothing # UNCOMMENT FOR FOR OPTION 2
end
function OUTER!(always::Keep)
preAllocate = SVector{3}(0.0,0.0,0.0)
for i=1:length(always.dreaming)
always.dreaming[i] = INNER!(always.dreaming[i], preAllocate) # UNCOMMENT FOR FOR OPTION 1
#INNER!(always.dreaming[i], preAllocate) # UNCOMMENT FOR FOR OPTION 2
end
end
code = Keep([zero(SVector{3}) for i=1:5])
OUTER!(code)
println(code.dreaming)
I hope that I have understood your question correctly. It's a bit hard with a MWE like this, that does a lot of things that are mostly redundant and a bit confusing.
There seems to be two alternative interpretations here: Either you really need to update ('mutate') an SVector, but your MWE fails to demonstrate why. Or, you have convinced yourself that you need to mutate, but you actually don't.
I have decided to focus on alternative 2: You don't really need to 'mutate'. Rewriting your code from that point of view simplifies it greatly.
I couldn't find any reason for you to mutate any static vectors here, so I just removed that. The behaviour of the INNER! function with the inputs was very confusing. You provide two inputs but don't use either of them, so I removed those inputs.
function inner()
pre = #SVector [rand() * 1000i for i in 1:3]
x = 25
return pre .* x
end
function outer!(always::Keep)
always.dreaming .= inner.() # notice the dot in inner.()
end
code = Keep([zero(SVector{3}) for i in 1:5])
outer!(code)
display(code.dreaming)
This runs fast and with zero allocations. In general with StaticArrays, don't try to mutate things, just create new instances.
Even though it's not clear from your MWE, there may be some legitimate reason why you may want to 'mutate' an SVector. In that case you can use the setindex method of StaticArrays, you don't need Setfield.jl:
julia> v = rand(SVector{3})
3-element SArray{Tuple{3},Float64,1,3}:
0.4730258499237898
0.23658547518737905
0.9140206579322541
julia> v = setindex(v, -3.1, 2)
3-element SArray{Tuple{3},Float64,1,3}:
0.4730258499237898
-3.1
0.9140206579322541
To clarify: setindex (without a !) does not mutate its input, but creates a new instance with one index value changed.
If you really do need to 'mutate', perhaps you can make a new MWE that shows this. I would recommend that you try to simplify it a bit, because it is quite confusing now. For example, the inclusion of the type Keep seems entirely unnecessary and distracting. Just make a Vector of SVectors and show what you want to do with that.
Edit: Here's an attempt based on the comments below. As far as I understand it now, the question is about modifying a vector of SVectors. You cannot really mutate the SVectors, but you can replace them using a convenient syntax, setindex, where you can keep some of the elements and change some of the others:
oldvec = [zero(SVector{3}) for _ in 1:5]
replacevec = [rand(SVector{3}) for _ in 1:5]
Now we replace the second element of each element of oldvec with the corresponding one in replacevec. First a one-liner:
oldvec .= setindex.(oldvec, getindex.(replacevec, 2), 2)
Then an even faster one with a loop:
for i in eachindex(oldvec, replacevec)
#inbounds oldvec[i] = setindex(oldvec[i], replacevec[i][2], 2)
end
There are two types of static arrays - mutable (starting with M in type name) and immutable ones (starting with S) - just use the mutable ones! have a look at the example below:
julia> mut = MVector{3,Int64}(1:3);
julia> mut[1]=55
55
julia> mut
3-element MArray{Tuple{3},Int64,1,3}:
55
2
3
julia> immut = SVector{3,Int64}(1:3);
julia> inmut[1]=55
ERROR: setindex!(::SArray{Tuple{3},Int64,1,3}, value, ::Int) is not defined.
Let us see some simple benchmark (ordinary array, vs mutable static vs immutable static):
using BenchmarkTools
julia> ord = [1,2,3];
julia> #btime $ord.*$ord;
39.680 ns (1 allocation: 112 bytes)
3-element Array{Int64,1}:
1
4
9
julia> #btime $mut.*$mut
8.533 ns (1 allocation: 32 bytes)
3-element MArray{Tuple{3},Int64,1,3}:
3025
4
9
julia> #btime $immut.*$immut
2.133 ns (0 allocations: 0 bytes)
3-element SArray{Tuple{3},Int64,1,3}:
1
4
9

Looping over array values in Lua

I have a variable as follows
local armies = {
[1] = "ARMY_1",
[2] = "ARMY_3",
[3] = "ARMY_6",
[4] = "ARMY_7",
}
Now I want to do an action for each value. What is the best way to loop over the values? The typical thing I'm finding on the internet is this:
for i, armyName in pairs(armies) do
doStuffWithArmyName(armyName)
end
I don't like that as it results in an unused variable i. The following approach avoids that and is what I am currently using:
for i in pairs(armies) do
doStuffWithArmyName(armies[i])
end
However this is still not as readable and simple as I'd like, since this is iterating over the keys and then getting the value using the key (rather imperatively). Another boon I have with both approaches is that pairs is needed. The value being looped over here is one I have control over, and I'd prefer that it can be looped over as easily as possible.
Is there a better way to do such a loop if I only care about the values? Is there a way to address the concerns I listed?
I'm using Lua 5.0 (and am quite new to the language)
The idiomatic way to iterate over an array is:
for _, armyName in ipairs(armies) do
doStuffWithArmyName(armyName)
end
Note that:
Use ipairs over pairs for arrays
If the key isn't what you are interested, use _ as placeholder.
If, for some reason, that _ placeholder still concerns you, make your own iterator. Programming in Lua provides it as an example:
function values(t)
local i = 0
return function() i = i + 1; return t[i] end
end
Usage:
for v in values(armies) do
print(v)
end

Pass Array to Subroutine IDL

I have a very long lookup table (~40,000 lines) that I am using for my code. Currently, I have it set to grab 4 arrays from my lookup table in the subroutine that uses it, but I call that subroutine ~3,000 times. I would rather not waste processing time grabbing this table as arrays repeatedly. Is there a way to grab them in my main program, store them, and source them later in my subroutine?
My current code grabs the lookup table in 4 separate arrays of 39,760 lines, and I am currently calling it like this:
READCOL, 'LookupTable2.txt', F='D,D,D,D',Albedo, Inertia, NightT, DayT
EDIT: I should probably note I have IDL 6.2, but if there is a way to do it in a newer version, I would still appreciate knowing how.
EDIT 2: My current program has a function which saves 4 arrays and executes the main function. Can I call my function with arrays as an argument? That way I wouldn't have to keep creating the same array
Something like:
Pro
FUNC(Array1, Array2, Var1, Var2, Var3)
END
There are several ways you can do this.
It looks like you have four columns and 40,000 lines, correct?
Then you can do the following. First, I will assume there is no header data in the ASCII file for the following commands.
FUNCTION read_my_file,file_name
;; Assume FILE_NAME is full path to and including file name with extension
fname = file_name[0]
;; One could also find the file with the following
;; fname = FILE_SEARCH([path to file],[file name with extension])
;; Define the number of lines in the file
nl = FILE_LINES(fname[0])
;; Define empty arrays to fill
col1 = DBLARR(nl[0])
col2 = DBLARR(nl[0])
col3 = DBLARR(nl[0])
col4 = DBLARR(nl[0])
dumb = DBLARR(4)
;; Open file
OPENR,gunit,fname[0],ERROR=err,/GET_LUN
IF (err NE 0) THEN PRINT, -2, !ERROR_STATE.MSG ;; Prints an error message
FOR n=0L, nl[0] - 1L DO BEGIN
;; Read in file data
READF,gunit,FORMAT='(4d)',dumb
;; Fill arrays
col1[n] = dumb[0]
col2[n] = dumb[1]
col3[n] = dumb[2]
col4[n] = dumb[3]
ENDFOR
;; Close file
FREE_LUN,gunit
;; Define output
output = [[col1],[col2],[col3],[col4]]
;; Return to calling routine
RETURN,output
END
Note that this will work better if you provide an explicit width for the format statement, e.g., '(4d15.5), which means a 15 character input with 5 decimal places.
This will return col1 through col4 to the user or calling routine as an [N,4]-element array, e.g., col1 = output[*,0]. You could use a structure where each tag contains one of the colj arrays or you could return them through keywords.
Then you can pass these arrays to another function/program in the following way:
PRO my_algorithm_wrapper,file_name,RESULTS=results
;; Get data from files
columns = read_my_file(file_name)
;; Pass data to [algorithm] function
results = my_algorithm(columns[*,0],columns[*,1],columns[*,2],columns[*,3])
;; Return to user
RETURN
END
To call this from the command line (after making sure both routines are compiled), you would do something like the following:
IDL> my_algorithm_wrapper,file_name,RESULTS=results
IDL> HELP,results ;; see what the function my_algorithm.pro returned
The above code should work with IDL 6.2.
General Notes
Try to avoid using uppercase letters in IDL routine names as it can cause issues when IDL searches for the routine during a call or compilation statement.
You need to name the program/function in the line with the PRO/FUNCTION statement at the beginning of the file. The name must come immediately after the PRO/FUNCTION statement.
It is generally wise to use explicit formatting statements to avoid ambiguities/errors when reading data files.
You can pass any variable type (e.g., scalar integer, array, structure, object, etc.) to programs/functions so long as they are handled appropriately within the program/function.

Do loop index changing on its own

I have a couple hundred line program (including functions) in essentially free-form Fortran. At one point, I have a pair of nested do loops that call functions and store results in matrices. However, I don't believe any of that is the problem (although I could be wrong).
Immediately after the first do loop starts, I define an array using a column of another array. Immediately after that, the index is always set to 3. I haven't been able to find any useful information in the usual places. I've included a fragment of the code below.
do i = 1,n
print *, 'i:',i ! Gives i = 1
applyto = eig_vec(:,i)
print *, i ! Gives i = 3
state1 = create_state(ground,applyto,state,bin_state,num_s,ns)
first = destroy_state(ground,state1,state,bin_state,num_s,ns)
state1 = destroy_state(ground,applyto,state,bin_state,num_s,ns)
second = create_state(ground,state1,state,bin_state,num_s,
1 ns)
do j = 1,n
bra = eig_vec(:,j)
a_matrix(j,i) = sum(bra*first + bra*second)
matrix(j,i) = sum(bra*first - bra*second
end do
end do
Is this a bug? Am I missing something obvious? I am compiling the code with a high level of optimization, if that could potentially be a source of problems. I'm relatively new to Fortran, so debugging flags or commands (for gdb - I believe that's all I have available) would be welcome.

Resources