"You can't beat a good compiler... right?"

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
pocopito
Posts: 238
Joined: Tue Jul 12, 2011 1:31 pm

"You can't beat a good compiler... right?"

Post by pocopito »

Hi all

I just found this blog entry about how to improve a piece of C code by studying the assembly output:

http://lbrandy.com/blog/2010/06/you-can ... d-compile/

What called my attention was the simpleness of the improved code and the "improving factor" (almost 5 times faster). The original code looks like:

Code: Select all

#define LENGTH 5000

// a bad impersonation of a gaussian filter
const float filter[] = {0.01f, 0.2f, 0.58f, 0.2f, 0.01f};

void naive(float* in, float* out)
{
  int i,j;
  for (i=0;i<LENGTH-4;i++)
  {
    out[i]=0.0f;
    for (j = 0;j<5;j++)
      out[i] += filter[j] * in[i+j];
  }
}
My knowledge on the topic is almost null, so probably it's not that interesting, but just in case I post it in the forum.

Best

E Diaz
Two first meanings of the dutch word "leren":
1. leren [vc] (learn, larn, acquire) acquire or gain knowledge or skills.
2. leren [v] (teach, learn, instruct) impart skills or knowledge to.
mar
Posts: 2676
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: "You can't beat a good compiler... right?"

Post by mar »

Hi,
this is about aliasing. The compiler doesn't know wheter in and out overlap. You can explicitly tell with restrict (a hint), but you have no guarantee that your compiler actually supports it.
Any (sane) programmer would use a temporary variable instead, which will be stored in a register:

Code: Select all

void naive(float* in, float* out)
{
  int i,j;
  for (i=0;i<LENGTH-4;i++)
  {
    float temp=0;
    for (j = 0;j<5;j++)
      temp += filter[j] * in[i+j];
    out[i] = temp;
  }
}
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: "You can't beat a good compiler... right?"

Post by lucasart »

mar wrote:Hi,
this is about aliasing. The compiler doesn't know wheter in and out overlap. You can explicitly tell with restrict (a hint), but you have no guarantee that your compiler actually supports it.
Any (sane) programmer would use a temporary variable instead, which will be stored in a register:

Code: Select all

void naive(float* in, float* out)
{
  int i,j;
  for (i=0;i<LENGTH-4;i++)
  {
    float temp=0;
    for (j = 0;j<5;j++)
      temp += filter[j] * in[i+j];
    out[i] = temp;
  }
}
Thanks, that's interesting to know. I didn't read the article, but after looking at the initial code sample, I didn't see what was wrong with it. I naively assumed that out would be seen by the compiler as a loop invariant, but as you say, that's only OK if in and out do not overlap.

Something to think about when writing performance critical code.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.