I simply define and read two arrays of 64 KBs each, storing their values in a local variable. The difference is that in the first chunk of code I access memory sequentially, taking advantage of the cache, whereas in the second chunk I access in strides of 64 bytes, which in turn causes cache misses and more frequent access to main memory.

The results are astonishing: the first chunk (the cache-friendly code) executes an average of 7.3 times faster. So yes! Memory is an important bottleneck in today's systems.

jueves, 13 de noviembre de 2014

Today, I bring you a short explanation, which is not directly tied to games programming, but just programming in general. However, I think it's something useful as you may find what I'll explain here in libraries that you may use in your games.

The explanation is about the keyword extern for specifying C linkage. Note that the keyword "extern" has another meaning when it precedes variables or function names, but we're dealing here with a different use, in particular, with the following one:

extern "C"

{

//Headers (.h) or functions declarations

}

With the above statement, we're telling the C++ compiler the following: "Listen guy, I have several functions (or headers, which in turn comprise several functions) that were compiled with a C compiler, but I want to be able to call these functions from my C++ code".

And why would you need this? What's the difference that makes C and C++ unable to talk to each other natively? The problem is name mangling due to function overloading. C++ allows overloading functions, so the C++ compiler needs to use both the function name and arguments information in order to provide a unique identifier for the function. Since C does not allow overloading, it does not need to use name mangling. If you used name mangling, the C++ linker would look for function names that are mangled, but it wouldn't find them because the C compiler didn't mangle the names. So basically, when you use extern "C", you're deactivating the default C++ name mangling for the functions declared inside the block.

A short example comes now. Suppose you have the following C header/implementation:

//mymath.h

#ifndef MYMATH_H

#define MYMATH_H

int mySum(int x, int y);

#endif

//mymath.c

#include "mymath.h"

int mySum(int x, int y)

{

return (x + y);

}

Now, we compile this with a C compiler (suppose gcc):

gcc -c mymath.c

The above line generates an object file called mymath.o.

Now, let's make a simple C++ program that uses the above function like this:

So basically, the linker is telling us that it is unable to find the function with name mySum(int, int). The way to solve it is by informing the C++ compiler that mySum is actually a C function, so that it generates the appropriate name for it that the linker can find.

The symbol __cplusplus is defined only if the compiler is a C++ compiler. Therefore, suppose that we do the following in mymath.h:

//mymath.h

#ifndef MYMATH_H

#define MYMATH_H

#ifdef __cplusplus

extern "C"

{

#endif

int mySum(int x, int y);

#ifdef __cplusplus

}

#endif

#endif

We can still compile mymath.c because __cpluplus is 0 and "extern" will not make it to the object file (C does not understand extern "C"). And what's more important, this allows any C++ client code to be oblivious about whether it should specify or not C linkage. So now, maincpp.cpp would be like this: