views:

233

answers:

7

In general use, should I bet on memory efficiency or processor efficiency?

In the end, I know that must be according to software/hardware specs. but I think there's a general rule when there's no boundaries.

Example 01 (memory efficiency):

int n=0;   
if(n < getRndNumber())
    n = getRndNumber();

Example 02 (processor efficiency):

int n=0, aux=0;
aux = getRndNumber();
if(n < aux)
    n = aux;

They're just simple examples and wrote them in order to show what I mean. Better examples will be well received.

Thanks in advance.

A: 

Processor efficiency. Memory is egregiously slow compared to your processor. See this link for more details.

Although, in your example, the two would likely be optimized to be equivalent by the compiler.

Mike
+11  A: 

I'm going to wheel out the universal performance question trump card and say "neither, bet on correctness".

Write your code in the clearest possible way, set specific measurable performance goals, measure the performance of your software, profile it to find the bottlenecks, and then if necessary optimise knowing whether processor or memory is your problem.

(As if to make a case in point, your 'simple examples' have different behaviour assuming getRndNumber() does not return a constant value. If you'd written it in the simplest way, something like n = max(0, getRndNumber()) then it may be less efficient but it would be more readable and more likely to be correct.)


Edit:

To answer Dervin's criticism below, I should probably state why I believe there is no general answer to this question.

A good example is taking a random sample from a sequence. For sequences small enough to be copied into another contiguous memory block, a partial Fisher-Yates shuffle which favours computational efficiency is the fastest approach. However, for very large sequences where insufficient memory is available to allocate, something like reservoir sampling that favours memory efficiency must be used; this will be an order of magnitude slower.

So what is the general case here? For sampling a sequence should you favour CPU or memory efficiency? You simply cannot tell without knowing things like the average and maximum sizes of the sequences, the amount of physical and virtual memory in the machine, the likely number of concurrent samples being taken, the CPU and memory requirements of the other code running on the machine, and even things like whether the application itself needs to favour speed or reliability. And even if you do know all that, then you're still only guessing, you don't really know which one to favour.

Therefore the only reasonable thing to do is implement the code in a manner favouring clarity and maintainability (taking factors you know into account, and assuming that clarity is not at the expense of gross inefficiency), measure it in a real-life situation to see whether it is causing a problem and what the problem is, and then if so alter it. Most of the time you will not have to change the code as it will not be a bottleneck. The net result of this approach is that you will have a clear and maintainable codebase overall, with the small parts that particularly need to be CPU and/or memory efficient optimised to be so.

Greg Beech
I understand. Thanks. As a matter of fact, I realize I should study and know STL well enough in order to use ir more often and try to get the best out of it.
pctroll
I don't think this is helpful, even if it is a good answer. The question has not been answered. Fix the OP's example to something that makes more sense and answer the question. It's as if many people here had an IV dose of Dijkstra and serve only platitudes. Why not just answer the question? If the OP had in fact asked about correctness, then that would have been different.
Dervin Thunk
unless `max()` is a macro :) He he.
Alex
@Dervin - Does my edit address your criticism? Also, you know you're free to add your own answer if you don't agree with mine.
Greg Beech
A: 

In the past 10 years. main memory has increased in speed hardly at all, while processors have continued to race ahead. There is no reason to believe this is going to change.

Edit: Incidently, in your example, aux will most likely end up in a register and never make it to memory at all.

John Knoeller
The cost of memory has plummeted. Usually it's the size of memory vs. speed of processor tradeoff. I think your "speed of memory" isn't as relevant as the size of memory.
S.Lott
Reallly?I remember getting a 3 Ghz processor over 6 years ago.
Autopulated
Yeah, they maxed out clock speed a while ago, now they do more on each clock instead.
John Knoeller
A: 

It's also worth considering the scope of the operation you are looking to optimize; if the operation is time sensitive, say part of a web request or GUI update, it might be better to err on the side of completing it faster than saving memory.

Douglas F Shearer
+1  A: 

You have to decide based on the particular application, usage etc. In your above example, both memory and processor usage is trivial, so not a good example.

A better example might be the use of history tables in chess search. This method caches previously searched positions in the game tree in case they are re-searched in other branches of the game tree or on the next move.

However, it does cost space to store them, and space also requires time. If you use up too much memory you might end up using virtual memory which will be slow.

Another example might be caching in a database server. Clearly it is faster to access a cached result from main memory, but then again it would not be a good idea to keep loading and freeing from memory data that is unlikely to be re-used.

In other words, you can't generalize. You can't even make a decision based on the code - sometimes the decision has to be made in the context of likely data and usage patterns.

Larry Watanabe
+1  A: 

You think one is unrelated to the other? Why do you think that? Here are two examples where you'll find often unconsidered bottlenecks.

Example 1

You design a DB related software system and find that I/O is slowing you down as you read in one of the tables. Instead of allowing multiple queries resulting in multiple I/O operations you ingest the entire table first. Now all rows of the table are in memory and the only limitation should be the CPU. Patting yourself on the back you wonder why your program becomes hideously slow on memory poor computers. Oh dear, you've forgotten about virtual memory, swapping, and such.

Example 2

You write a program where your methods create many small objects but posses O(1), O(log) or at the worst O(n) speed. You've optimized for speed but see that your application takes a long time to run. Curiously, you profile to discover what the culprit could be. To your chagrin you discover that all those small objects adds up fast. Your code is being held back by the GC.

wheaties
A: 

Without context I think optimising for anything other than readability and flexibilty

So, the only general rule I could agree with is "Optmise for readability, while bearing in mind the possibility that at some point in the future you may have to optimise for either memory or processor efficiency in the future".

Sorry it isn't quite as catchy as you would like...

In your example, version 2 is clearly better, even though version 1 is prettier to me, since as others have pointed out, calling getRndNumber() multiple times requires more knowledge of getRndNumber() to follow.

Modan