Fighter2 has asked for the wisdom of the Perl Monks concerning the following question:
I have an Array that is pretty big. VERY big. Every 14 elements in the array is a set. And I need to do some operations with values stored in that array.
But the way it is currently written below, makes my program run out of memory. Can you help me? I wouldn't mind any working option.
#Initialization my @in= (INSERT VERY LARGE ARRAY HERE); my $MaxAgc0 = "1.15503129132678e-005"; # MaxAgc0 is a constant #Interpolation if (@in) { for (my $i = 0; $i < @in; $i += 14) { for(my $j=1;$j<=$in[$i];$j++){ #$j is the actual no. of sector +s. my $num=($in[$i+12]*$MaxAgc0); push @Attn, $num/$in[$i+10]; } } for (my $i = 0; $i < @in; $i += 14) { push @powers, ($in[$i + $_] - $Attn[$i])/100 for (2..9); } } else { # @in is empty print "\n No data to map for Panda machine. Check if input logfile + is empty"; kill; }
I need the values in @powers
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Can you help profile this?
by Tanktalus (Canon) on Dec 08, 2011 at 23:34 UTC | |
First thing's first. If you have sets embedded in your list, keep them as sets. What you're doing is nearly the same thing as pointer arithmetic in C, and is bad for many of the same reasons. ww mentioned an AoA, but as a question. I'll make it a statement: it should be an array of references. Personally, I'm a bit more partial to AoH, as it allows me to use names for keys to make sense of the inner data. An AoA would look like: but we still don't know what any of the numbers mean without more context. An AoH usually would take up a lot more memory, but would give the context implicitly: You can get hashes to take a lot less memory if you can define "default" values that cover most cases, reducing most of the hashes down to only unique values, at a slight cost to code complexity. I'll assume that's not an option (it rarely is, in my experience). Once you do this, you would have $in[$i][12] or $in[$i]{attn} instead of $in[$i+12] Your outer for loop would be a simple for my $i (0..$#in) (you would want to go through the indexes, and the last one is the last index, which is what $# gives you). You wouldn't be creating an @Attn the length of your original array, but 1/14th the size, which would help both memory usage and speed. Also, your inner arrays would be arbitrary lengths - so if you regularly have less than 13 items in a set, you simply would not allocate the extra memory. And, should you need more than 14 items in a set, you can now handle that, kind of. Here's a first crack: Now, what I'd do from here is pull apart the sets even more. Say something like this: I'd also change the output to match everything done above: return a list of arrays: Now the return will keep the sectors grouped, there will be no extra data in the output. We can still improve this by getting rid of @Attn altogether: We got rid of a huge amount of wasted memory. That @Attn list was humongous in your code, and we've pared it down to 1/14th and now to a single scalar (which we calculate as we need it, then discard it once no longer needed). And we got rid of unnecessary items in your sets, though, in the interests of readability, I increased the memory usage of the input by making it an AoH's. That's probably a wash, if not slightly bigger now than it was. Hope that helps. | [reply] [d/l] [select] |
|
Re: Can you help profile this?
by Eliya (Vicar) on Dec 08, 2011 at 20:58 UTC | |
It's not clear to me what the @Attn array is supposed to be used for. As the number of iterations of the loop depends on the data (i.e. $in[$i] — which you haven't specified), it's not clear how many items are actually pushed onto the array. Also, all values pushed in one run of the loop seem to be same, because $j is never used in the computation. And then later, you index @Attn with multiples of 14 ... Questions over questions — at least for me :) Could you elaborate a bit more? | [reply] [d/l] [select] |
|
Re: Can you help profile this?
by ww (Archbishop) on Dec 08, 2011 at 22:21 UTC | |
First, neither your question nor your code makes it clear (to me, anyway; YMMV) precisely what you're trying to do; what the result of all this processing is supposed to provide, other than "values in @powers." But, in hopes your answers may shed some light on the matter: And does this -- in any way -- resemble what you want?
Output
WAG: Given your reference to a "set", could it be that @in is supposed to be an AoA? And, given the recommendation that SOPW include a minimal sample of code and data which reproduce the problem, why bother with the else clause when @in is (pseudo-)instantiated at your line 2? | [reply] [d/l] [select] |
by BrowserUk (Patriarch) on Dec 08, 2011 at 22:32 UTC | |
In your line 7, did you intend for $i < @in; to be $i < $#in; ? ... or, maybe $i < ( $#in + 1 );? @in is the entire array; not a count of elements How does someone who's been around here as long as you, miss the fact that an array reference @a in a scalar context (as provided by a comparison operator), renders the number of elements in the array. Ie. exactly the same number as $#a + 1? With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
by ww (Archbishop) on Dec 08, 2011 at 22:39 UTC | |
Is that a trick question? ... and I don't even know whether to follow that with a smiley or a frown. So I guess the best sequel is to say "My bad; apologies!." And likewise to Riales for Re^2: Can you help profile this? ++, both, and - -, /me. | [reply] |
by Riales (Hermit) on Dec 08, 2011 at 22:34 UTC | |
Regarding the bit about line 7: An array evaluated in scalar format returns the length of the array. So @in would indeed have returned a count of its elements. Also, $#in would return the last index of @in. This would mean that the middle expression in your for loops to: $i <= $#in. | [reply] [d/l] |
|
Re: Can you help profile this?
by Riales (Hermit) on Dec 08, 2011 at 21:48 UTC | |
Actually, now that I wrote that out, I'm thinking you don't even need to build @Attn (again, untested):
EDIT: All the above code may be wrong. I misread what the j-loop was doing in the original code; I had thought you were comparing to a slice of @in for some reason, but that's apparently not the case. I'm confused though...does the input data provide some sort of meta-information that you're reading in at every 14th element? My initial thought was that @Attn and @in were meant to be parallel arrays, but with the limit of the j-loop being defined that way, this would probably not be true... | [reply] [d/l] [select] |