Moore’s Law Problem [closed] - moores-law

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
Suppose you need to run a program on the world’s fastest supercomputer which will take 10 years to complete. You could:
Spend $250M now
Program for 9 years, Moore’s law speedup (4,000x faster), spend $1M in 10years, complete in 2 weeks.
What is the optimum strategy?
Question from "Long Term Storage Trends and You"

Moore's Law is not about speed, it's about the number of transistors in a given area of silicon. There is no guarantee that in 9 years the speed will increase 4000x. If anything, GHz speed has levelled off in recent years. What is increasing, currently, is the number of cores in a CPU.
In your question, if the program does not lend itself to vectorisation (i.e. can be split into distinct parts that can be computed in parallel) then waiting 9 years will not provide any benefit, it won't be that much faster as clock speeds are unlikely to raise much in the intervening years.

Assuming the program is infinitely parallelizable (so it can always take advantage of all cores of all CPUs available)...
Assuming the program cannot be paused and moved to a different machine in mid-run...
Assuming time is the only issue (maybe we have a big research grant and we always use the best computers available)...
We have four equations (well, actually two of them are functions):
endtime(startyear) = startyear + (calculations / speed(startyear))
speed(year) = speed(year-1.5)4 (the problem assumes both hardware and software double in speed every 18 months)
endtime(0) = 0 + (calculations/speed(0)) = 10 years
speed(0) = calculations/(10 years) (implied by #3)
I started to use derivatives to minimize endtime, but I realized I can't remember my differential equations very well. So I transformed #2 into the equivalent exponential-growth formula:
speed(year) = speed(0)*4(year/1.5) = (calculations/10)*4(year/1.5)
Then I wrote this little BeanShell script:
calculations() {
return 10000000; // random constant (gets cancelled out anyway)
}
speed(year) {
speed0 = calculations()/10; // constant factor
return speed0*Math.pow(4.0, year/1.5);
}
endtime(startyear) {
return startyear + calculations()/speed(startyear);
}
findmin() {
start = 0.0;
finish = 10.0;
result = 0.0;
// home in on the best solution (there should only be one minimum)
for (inc = 1; inc > 0.00000001; inc /= 2.0) {
result = findmin(start,finish,inc);
start = result-2*inc;
finish = result+inc;
}
print("Minimum value is " + result + ", taking a total of " +
endtime(result) + " years");
}
findmin(start,finish,inc) {
lastNum = 0;
lastVal = Double.MAX_VALUE;
for (i = start; i < finish; i += inc) {
result = endtime(i);
if (result > lastVal) {
print("Minimum value between " + start + " and " + finish +
" is " + lastVal + ", occurring at " + lastNum);
return i;
}
lastNum = i;
lastVal = result;
}
return lastNum;
}
Output:
bsh % source("moore.bsh");
bsh % findmin();
Minimum value between 0.0 and 10.0 is 3.5749013123685915, occurring at 2.0
Minimum value between 1.0 and 4.0 is 3.4921256574801243, occurring at 2.5
Minimum value between 2.0 and 3.5 is 3.4921256574801243, occurring at 2.5
Minimum value between 2.25 and 3.0 is 3.4886233976754246, occurring at 2.375
Minimum value between 2.25 and 2.625 is 3.488620519067143, occurring at 2.4375
Minimum value between 2.375 and 2.5625 is 3.488170701257679, occurring at 2.40625
Minimum value between 2.375 and 2.46875 is 3.488170701257679, occurring at 2.40625
Minimum value between 2.390625 and 2.4375 is 3.488170701257679, occurring at 2.40625
(snip)
Minimum value between 2.406149387359619 and 2.4061494767665863 is 3.4881706965827037,
occurring at 2.4061494171619415
Minimum value is 2.4061494320631027, taking a total of 3.488170696582704 years
So, with the assumptions I stated before, the answer is to wait 2.406149... years (or approximately 2 years, 148 days, according to Google).
Edit: I noticed that with second formula rewritten as above, solving only requires simple calculus.
endtime(x) = x + c/speed(x) (where c = calculations)
speed(x) = speed(0) * 4^(x/1.5) = (c/10)*4^(2x/3)
=> endtime(x) = x + c/((c/10)*4^(2x/3))
= x + 10*(4^(-2x/3))
d/dx endtime(x) = 1 + 10*ln(4)*(-2/3)*(4^(-2x/3))
Critical point is when d/dx = 0, so
1 + 10*ln(4)*(-2/3)*(4^(-2x/3)) = 0
=> 4^(-2x/3) = 1/(10*ln(4)*(2/3))
Take log4 of both sides: (remember that log4(x) = ln(x)/ln(4), and that ln(1/x) = -ln(x))
-2x/3 = ln(1/(10*ln(4)*(2/3))) / ln(4)
= -ln(10*ln(4)*2/3) / ln(4)
=> x = (-3/2) * -ln(1/(10*ln(4)*2/3)) / ln(4)
= 3*ln(10*ln(4)*(2/3)) / 2*ln(4)
That looks like an awful mess (it doesn't help that there's no good way to show math formulas here). But if you plug it into your calculator, you should get 2.4061494159159814141268120293221 (at least if you use the Windows calculator, like I just did). So my previous answer was correct to seven decimal places (which are meaningless in a problem like this, of course).
(I should note that this is just a critical point, not necessarily a minimum. But the second derivative (which is of the form -(some constant)*4-2x/3) is always negative. So the function is always concave up, therefore the only critical point is the minimum.)

Moore's Law is concerned with the number of transistors that will be placed into one single chip and does not relate to the speed of microprocessors in general.
That said, from the current trend we are seeing, we'll probably see more and more cores being fit into a single processor die, so concurrent programming is going to become more and more important to take advantage of the raw processing power available in a processor.
So, it's hard to say whether to do it now or wait -- however, either way, concurrent programming or distributed computing is going to come into play, as we won't be seeing a single core processor becoming exponentially faster (in terms of clock speed) due to the physical limitations of current semiconductor technology and the laws of nature.

Make sure your program can pause and continue, and then put it on faster and faster machines as they come along. Best of both worlds...

Spend the money now - the price/value of the dollar now vs an estimate in 10 years is like trying to forecast weather 3 months from now. Plus this fails to consider factors like programming trends in 10 years and whether things will actually be 4,000 times faster or 4,000 times more scalable/parallel which seems to be the trend of late.
Also, according to the Mayans the world will end in 2012 so spend the loot now!

Simplify the model to make an estimate that you can run now. As more/better resources become available, refine the model for more accurate results.

The fastest way to complete it would be to:
Write a version for current technology that could be migrated to each new generation.
Alongside migrations, continue programming for any improvements algorithmically etc.
The cheapest way would obviously be to leave it for longer. You do need to factor in programming time (which would be near enough constant).
Also, I wouldn't want to stake too much on moore's law continuing.
Also remember that moore's law relates to the density of transistors not to computing speed for a particular problem. Even if computing power in general improves by that much, it doesn't necessarily mean your application will benefit.

But Moore's law does not speed up programming.
9 years of programming will never be condensed into 2 weeks.
Unless you successfully spend the 9 years programming an automated thought reading machine I suppose.

Program for 4 years and then run it in 2.5?
(I'm sure there's a "perfect" answer somwehere between 4 and 5 years...)

The optimum strategy depends on the reason you have to run the program.
In this scenario, the second option is the best one, because the moment you'll have the result (which is what actualy matters) would be the same.
Actually, I believe that if everybody choose the first one (and had the money to do that) ... the Moore's Law would be compromised. I assume that if all our computational needs were satisfied ... we wouldn't be so commited in keep the technology development moving forward.

This makes a flawed assumption that Moore's Law is actually a Law. It would probably be better named Moore's Theory. The risk you run by waiting is that in 10 years, it may still take 10 years to run. Start the program now (with pause and restart built in if possible), start a team looking at other ways to solve the problem that will be faster. Once you have confidence that one or the other will provide a quicker solution, switch.
EDIT: As a problem I think the best value in this question is that it makes you examine whether your assumptions are valid. The obvious solution -- since according to the problem definition you get the same result in the same amount of time with less money -- is to wait, but it depends on some implicit assumptions. If those assumptions don't hold, then the obvious solution is not necessarily the best as many answers here attest.

It's specified in the question that the problem runs on a super-computer, thus the problem must be vectorizable. The speed of of a super-computers is going up vastly faster than Moores law, so depending on the actual problem space one approach would be to hire hacker banditos to create a world wide distributed Warhol Worm that acquired the resources of 85% of the computers on the net for a short massively distributed grid like the Mersenne prime search (GIMPS) and solve the problem in 20 minutes.
(many ways to solve a problem but I sure hope this is labeled as humor)

Related

Front-End and Back-End calculating different amounts? Should the calculation be done in the same place?

So I have this issue with a website that I work on.
It goes like so (note: This is not exactly what happens. I am just painting a picture):
Front-End:
User has a cart full of things they want to buy
Front-End calculates the amount that should be paid (this calculates in discounts, sales, Buy One Get One, etc.)
User submits and pays the amount
Back-End:
Items are bought and money is received
Backend calculates a different amount for what everything should have cost
Backend wants either less or more money
I think that I should calculate the amount in the same place. I think in step 2 I could make a call to the backend to determine what the amount should be.
That way I wouldn't run into this issue where they are calculating 2 different amounts. What do you guys think?
If your frontend is implemented in JavaScript or some language that transcribes to JavaScript you should keep any business critical calculations (such as payment amounts) away from there. JavaScript logic is easy to manipulate in the browser and all critical code therefore needs to be executed in the backend server.
You should do exactly as you are suggesting and call your backend in step 2.
This will also make the system easier to maintain as you won't have duplicated logic in two places, any refactoring or debugging regarding this logic can be done in a single location in the codebase.
This is probably a problem with rounding and floating numbers. The rounding functions and systems representing the numbers can be differently defined when different programming languages are used. Either you can use a library to use decimal numbers or try to implement the rounding behavior for one side to match the other side. Then it is always advised to calculate with integers as much as possible. Multiplying with 100 at the beginning and dividing with 100 at the end of calculations help to stabilize the numbers. Also, you should consider using bankers round also called Half Even rounding as a strategy when rounding currencies to minimize the total failure.
For TypeScript the function could be:
function roundHalfEven(x: number, d: number) {
const p = Math.pow(10, d);
const xp = x * p;
const r = Math.round(xp);
return (Math.abs(xp) % 1 == 0.5 && r % 2 != 0 ? r - 1 : r) / p;
}
The line const xp = x * p; could also be made more stable with const xp = parseFloat((x * p).toPrecision(15)).
But also do never trust anything coming from the browser. So you should definitely check at the end on your server if everything adds up.
You can find more information on rounding and how to handle failures on the following pages:
Good answer on this topic but be aware that everything should be taken with a grain of salt. For example the solution to Math.round(-0.5) is -0 and not -1 as in Amr Alis response.
ICU on rounding The most important rounding methods with sample data.

How long does it take to crack a hash?

I want to calculate the time it will take to break a SHA-256 hash. So I research and found the following calculation. If I have a password in lower letter with a length of 6 chars, I would have 26^6passwords right?
To calculate the time I have to divide this number by a hashrate, I guess. So if I had one RTX 3090, the hashrate would be 120 MH/s (1.2*10^8 H/s) and than I need to calculate 26^6/(1.2*10^8) to get the time in seconds right?
Is this idea right or wrong?
Yes, but a lowercase-latin 6 character string is also short enough that you would expect to compute this one time and put it into a database so that you could look it up in O(1). It's only a bit over 300M entries. That said, given you're 50% likely to find the answer in the first half of your search, it's so fast to crack that you might not even bother unless you were doing this often. You don't even need a particularly fancy GPU for something on this scale.
Note that in many cases a 6 character string can also be a 5 character string, so you need to add 26^6 + 26^5 + 26^4 + ..., but all of these together only raises this to around 320M hashes. It's a tiny space.
Adding uppercase, numbers and the easily typed symbols gets you up to 96^6 ~ 780B. On the other hand, adding just 3 more lowercase-letters (9 total) gets you to 26^9 ~ 5.4T. For brute force on random strings, longer is much more powerful than complicated.
To your specific question, note that it does matter how you implement this. You won't get these kinds of hash rates if you don't write your code in a way to maximize the GPU. For example, writing simple code that sends one value to the GPU to hash at a time, and then compares the result on the CPU could be incredibly slow (in some cases slower than just doing all the work on a CPU). Setting up your memory efficiently and maximizing things the GPU can do in parallel are very important. If you're not familiar with this kind of programming, I recommend using or studying a tool like John the Ripper.

Python: Time and space complexity of gcd and recursive iterations

I’m studying for mid-terms and this is one of the questions from a past yr paper in university. (Questions stated below)
Given Euclid’s algorithm, we can write the function gcd.
def gcd(a,b):
if b == 0:
return a
else:
return gcd(b, a%b)
[Reduced Proper Fraction]
Consider the fraction, n/d , where n and d are positive integers.
If n < d and GCD(n,d) = 1, it is called a reduced proper fraction.
If we list the set of reduced proper fractions for n <=8 in ascending order of size, we get:
1/8,1/7,1/6,1/5,1/4,2/7,1/3,3/8,2/5,3/7,1/2,4/7,3/5,5/8,2/3,5/7,3/4,4/5,5/6,6/7,7/8
It can be seen that there are 21 elements in this set.
Implement the function count_fraction that takes an integer n and returns the number of reduced proper fractions for n. Assuming that the order of growth (in time) for gcd is O(logn), what is the order of growth in terms of time and space for the function you wrote in Part (B) in terms of n. Explain your answer.
Suggested answer.
def count_fraction(n):
if n==1:
return 0
else:
new = 0
for i in range(1,n):
if gcd(i,n) == 1:
new += 1
return new + count_fraction(n-1)
The suggested answer is pretty strange as the trend of this question in previous years, is designed to test purely recursive/purely iterative solutions, but it gave a mix. Nevertheless, I don’t understand why the suggested order of growth is given as such. (I will write it in the format, suggested answer, my answer and questions on my fundamentals)
Time: O(nlogn), since it’s roughly log1+log2+· · ·+log(n−1)+logn
My time: O(n^2 log n). Since there is n recursive function calls, each call has n-1 iterations, which takes O(log n) time due to gcd.
Question 1: Time in my opinion is counting number of iterations/recursions* time taken for 1 iteration/recursion. It’s actually my first time interacting with a mixed iterative/recursive solution so I don’t really know the interaction. Can someone tell me whether I'm right/wrong?
Space: O(n), since gcd is O(1) and this code is obviously linear recursion.
My space: O(n*log n). Since gcd is O(log n) and this code takes up O(n) space.
Question 2: Space in my opinion is counting number of recursions*space taken for 1 recursive call OR largest amount of space required among all iterations. In the first place, I would think gcd is O(log n) as I assume that recursion will happen log n times. I want to ask whether the discrepancy is due to what my lecturer said.
(I don’t really understand what my lecturers says about delayed operations for recursions on factorial or no new objects being formed in iteratives. How do u then accept the fact that there are NEW objects formed in recursion also no delayed operations in iteration).
If u can clarify my doubt on why gcd is O(1) instead of O(log n), I think if I take n*1 for recursion case, I would agree with the answer.
I agree with your analysis for of the running time. It should be O(n^2 log(n)), since you make n calls to gcd on each recursive call to count_fraction.
You're also partly right about the second question, but you get the conclusion wrong (and the supplied answer gets the right conclusion for the wrong reasons). The gcd function does indeed use O(log(n)) space, for the stack of the recursive calls. However, that space gets reused for each later call to gcd from count_fraction, so there's only ever one stack of size log(n). So there's no reason to multiply the log(n) by anything, only add it to whatever else might be using memory when the gcd calls are happening. Since there will also be a stack of size O(n) for the recursive calls of count_fraction, the smaller log(n) term can be dropped, so you say it takes O(n) space rather than O(n + log(n)).
All in all, I'd say this is a really bad assignment to be trying to learn from. Almost everything in it has an error somewhere, from the description saying it's limiting n when it's really limiting d, to the answers you describe which are all at least partly wrong.

Dynamic Programming algorithm shortest path between two

There's an algorithm currently driving me crazy.
I've seen quite a few variations of it, so I'll just try to explain the easiest one I can think about.
Let's say I have a project P:
Project P is made up of 4 sub projects.
I can solve each of those 4 in two separate ways, and each of those modes has a specific cost and a specific time requirement:
For example (making it up):
P: 1 + 2 + 3 + 4 + .... n
A(T/C) Ta1/Ca1 Ta2/Ca2 etc
B(T/C) Tb1/Cb1 etc
Basically I have to find the combination that of those four modes which has the lowest cost. And that's kind of easy, the problem is: the combination has to be lower than specific given time.
In order to find the lowest combination I can easily write something like:
for i = 1 to n
aa[i] = min(aa[i-1],ba[i-1]) + value(a[i])
bb[i] = min(bb[i-1],ab[i-1]) + value(b[i])
ba[i] = min(bb[i-1],ab[i-1]) + value(b[i])
ab[i] = min(aa[i-1],ba[i-1]) + value(a[i])
Now something like is really easy and returns the correct value every time, the lowest at the last circle is gonna be the correct one.
Problem is: if min returns modality that takes the last time, in the end I'll have the fastest procedure no matter the cost.
If if min returns the lowest cost, I'll have the cheapest project no matter the amount of time taken to realize it.
However I need to take both into consideration: I can do it easily with a recursive function with O(2^n) but I can't seem to find a solution with dynamic programming.
Can anyone help me?
If there are really just four projects, you should go with the exponential-time solution. There are only 16 different cases, and the code will be short and easy to verify!
Anyway, the I'm pretty sure the problem you describe is the knapsack problem, which is NP-hard. So, there will be no exact solution that's sub-exponential unless P=NP. However, depending on what "n" actually is (is it 4 in your case? or the values of the time and cost?) there may be a pseudo-polynomial time solution. The Wikipedia article contains descriptions of these.

Solving Acceleration for Time with a limited velocity [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 8 years ago.
Improve this question
I'm working on a calculator in Excel for interstellar travel times. I'm currently solving an equation for Acceleration for Time to arrival like so:
=sqrt(distance*2/acceleration)
which seems to work fine for me, except that if I give it a large enough acceleration and long enough distance, I get a maximum velocity back that is higher than the speed of light.
What I want to do is add in some limiting factor into the formula that limits the velocity to some number, but I have no idea how to do this in the mathematics (disclaimer: I'm a writer and artist, so I suck badly at math). I think I need to integrate something like V=min(C,d/t) where C is the speed of light, but I don't know how to integrate that into my function. Since the rest of this works without having to chart out periods of time, I'd prefer a solution in the formula rather than some roundabout recursive chart trickery. Any ideas?
The right solution is of course to use the relativistic equation for the velocity after "constant acceleration" (which doesn't exist when you get near the speed of light). I suspect you mean "constant apparent acceleration" (what the passengers in the rocket feel). In that case, relativistically,
v = c * tanh(asinh(F*t/m*c))
Where
v = velocity
F = force
t = time
m = mass
c = speed of light
Then you can write F = m * a so acceleration = F / m
which you can write in Excel (after defining the constant C_ = 3E8 )
= C_ * TANH(ASINH(acceleration*time/C_)
This will initially give you linear acceleration as expected - then it will taper off and never quite reach the speed of light:
It seems to me that this equation is "the right one" for your particular application - you are not really trying to be super accurate, just have something that at least doesn't go faster than the speed of light, and transitions smoothly. In reality, what a rocket motor can do at these very high velocities, how the mass of the rocket is changing - all those things make the math a lot more complicated.
update if you want to achieve a result like the above but only have "distance" and "acceleration", we need to be a little bit tricky. Of course distance is something that depends on your frame of reference - it's different for the people in the rocket vs a stationary observer. So we are going to throw "real physics" out of the window for a minute and do something else. The straight red line in my plot represents "how fast you would be going if you kept accelerating" - this is the velocity of your initial calculation.
You can convert that to the "real" velocity with a simple
limitedVelocity = C_ * TANH(ASINH(calculatedVelocity / C_))
This is more in keeping with the question you asked, and allows you to stay in the framework you had (where you know "acceleration" and "distance" - whatever those mean in your world.)
Relativity. Blows your mind.
Afterthought
An accelerating space ship is in a non inertial frame of reference. The clock on board runs at a different speed (slower) than the "clock in the universe". Inside the spaceship the distance to their destination appears to shrink (Lorentz contraction) as they go faster. All this means that the "real" calculation depends on factors and assumptions that were not explicitly stated in the question. But since this is about an "interstellar travel calculator" by a self-professed non-physicist I think it is better not to turn this into a second year Physics of General Relativity course.
You can use an IF statement:
IF(logical_test, [value_if_true], [value_if_false])
As in:
=IF( sqrt(distance*2/acceleration) > C , C , sqrt(distance*2/acceleration) )

Resources