An 2011 i7-2600K desktop CPU is still competitive with current generation i7 CPUs for general-purpose computing – most improvements were in specialized instruction sets like AVX or TSX (which infamously was broken on the first generation shipping it). Lower-end i3 and i5 are even worse off, because they don't get most acceleration instruction sets in the first place.
For consumers, it makes absolutely no sense to upgrade their desktop PCs unless they break.
The way I see it, this is our fault as software developers. A 2016 PC would be much faster than a 2011 PC if we as software developers made good use of SIMD and GPUs. But we don't.
3D rendering, video editing, and music production all need as many cycles as you can afford, and then some.
VR and all those AI/ML technologies waiting around the corner are going to be even more greedy.
At work, our CAD people use Autodesk Inventor heavily, and that thing will happily gobble up all the CPU cycles one can throw at it. (It it the one example I have first-hand experience with.)
What I meant was that for most users of desktop PCs in an office environment, a faster CPU is not going to make much of a difference in overall system performance. (I might be a little sore because at work, users will sometimes complain there computer is too slow and then demand a new one with an i7, and then I have to explain to them why that is not going to help, while a RAM upgrade and an SSD are going to make a big difference.)
But you are right, there are plenty of examples where there is no such thing as "fast enough". ;-)
void blur(const Image &in, Image &blurred) {
Image tmp(in.width(), in.height());
for (int y = 0; y < in.height(); y++){
for (int x = 0; x < in.width(); x++){
tmp(x, y) = (in(x-1, y) + in(x, y) + in(x+1, y))/3;
}
}
for (int y = 0; y < in.height(); y++){
for (int x = 0; x < in.width(); x++){
blurred(x, y) = (tmp(x, y-1) + tmp(x, y) + tmp(x, y+1))/3;
}
}
}
The optimised-for-speed version (order of magnitude difference): void fast_blur(const Image &in, Image &blurred) {
m128i one_third = _mm_set1_epi16(21846);
#pragma omp parallel for
for (int yTile = 0; yTile < in.height(); yTile += 32) {
m128i a, b, c, sum, avg;
m128i tmp[(256/8)*(32+2)];
for (int xTile = 0; xTile < in.width(); xTile += 256) {
m128i *tmpPtr = tmp;
for (int y = -1; y < 32+1; y++) {
const uint16_t *inPtr = &(in(xTile, yTile+y));
for (int x = 0; x < 256; x += 8) {
a = _mm_loadu_si128(( m128i*)(inPtr-1));
b = _mm_loadu_si128(( m128i*)(inPtr+1));
c = _mm_load_si128(( m128i*)(inPtr));
sum = _mm_add_epi16(_mm_add_epi16(a, b), c);
avg = _mm_mulhi_epi16(sum, one_third);
_mm_store_si128(tmpPtr++, avg);
inPtr += 8;
}
}
tmpPtr = tmp;
for (int y = 0; y < 32; y++) {
m128i *outPtr = ( m128i *)(&(blurred(xTile, yTile+y)));
for (int x = 0; x < 256; x += 8) {
a = _mm_load_si128(tmpPtr+(2*256)/8);
b = _mm_load_si128(tmpPtr+256/8);
c = _mm_load_si128(tmpPtr++);
sum = _mm_add_epi16(_mm_add_epi16(a, b), c);
avg = _mm_mulhi_epi16(sum, one_third);
_mm_store_si128(outPtr++, avg);
}
}
}
}
}
I don't know about you, but that looks like an error prone maintenance disaster waiting to happen.And, just for comparison, Halide code that produces results as fast as the second code:
Func halide_blur(Func in) {
Func tmp, blurred;
Var x, y, xi, yi;
// The algorithm
tmp(x, y) = (in(x-1, y) + in(x, y) + in(x+1, y))/3;
blurred(x, y) = (tmp(x, y-1) + tmp(x, y) + tmp(x, y+1))/3;
// The schedule
blurred.tile(x, y, xi, yi, 256, 32).vectorize(xi, 8).parallel(y);
tmp.chunk(x).vectorize(x, 8);
return blurred;
}(this is kind of a weird coincidence; last time I replied to you I mentioned Halide[1] as well)
(defun language-choice (developer)
(if (> (developer-hipness developer) (developer-experience developer)) (lang-du-jour)
(if (developer-scared-of developer 'parenthesis)
(c-family-language)
(lisp-family-language))))