Memory efficiency vs Processor efficiency

2020-07-24 04:13发布

问题:

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.

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

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.



回答5:

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.



回答6:

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.



回答7:

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.