🔒 Locked
Low level programming guidance
Advertisement
Original Post
Ok so I’ve got my eye on a programming job, but it requires the candidate to have some experience with low level programming. What i was wondering is, where does low level programming fit game programming as a whole? What situations would you apply low level programming and what are the benefits? With this in mind, can anyone recommend a starting point for me? I have done a litte background reading and am guessing i should start by doing some assembly. I would assume that you'd use low level programming in addition to C++ (or whatever language your using) and in that case i could do it using Visual Studio? If anyone could help me out that would be great.
Not that I've ever done these things but I know you can program hardware shaders in assembly language and you can write fast math routines like sqrt, matrix multiplication, etc, in assembler to take advantage of SSE/3DNow type instructions on the CPU.
usually in the modern day the lowest level you would have to program at is with something like the windows api, goes to show how much I know. assembly is the lowest form of programming you would want to go (because binary is just suicide). what I would do is get some older books on assembler. oh btw you can use c++ with assembly, but I think you can only use hooks.
Mastersmith, cheers for the info. What do you mean by hooks?
Ok so maybe having a bit of assembly under my belt might help, even if its not directly related it would be best to understand whats going on if i look at some code. A friend of my who also interviewed there said i should look up bit-shifting, which i've heard about and i understand is kinda low level. But is that in the same vein as assembly?
Ok so maybe having a bit of assembly under my belt might help, even if its not directly related it would be best to understand whats going on if i look at some code. A friend of my who also interviewed there said i should look up bit-shifting, which i've heard about and i understand is kinda low level. But is that in the same vein as assembly?
I don't know what bit shifting is, but since it has the word bit in it I would lean towards it being pretty low level (maybe not assembly low, but still pretty low). what I mean by hooks is like little snippets of assembler in your code or like predefined files that you hook into your program. and it would be good for any programmer to have atleast a basic overview of how everything works at a low level.
but be warned if your going to mess with assembler, back up your hd, because you are working with the memory and cpu at the lowest levels you can really mess up your computer.
hope my info helps you :D.
http://www.freetechbooks.com/forum-27.html
this site provides some stuff for assembler, even for modern day stuff.
but be warned if your going to mess with assembler, back up your hd, because you are working with the memory and cpu at the lowest levels you can really mess up your computer.
hope my info helps you :D.
http://www.freetechbooks.com/forum-27.html
this site provides some stuff for assembler, even for modern day stuff.
Oh ok, cheers for the help mastersmith. If anyone else has anything to add please do so.
Bit-shifting as in:
x = y >> 32;
??
My guess is that when they ask for low-level programming, they're talking about assembly. In a game development context, the only kind of assembly you're ever going to write is usually inline-assembly, so something like (stupid example):
Much more important than knowing the actual assembly instructions however is knowing about CPU architecture and data representation. That knowledge will also help you with writing more efficient high-level programs.
Things you should know:
- How are integers (signed and unsigned) represented in memory. Hint: twos-complement
- How are floats represented in memory. Hint: IEEE 754, mantissa, exponent...
- How is memory organized in general (code, stack, heap,...)
- How does memory allocation with new/malloc work
- How does alloca work (not saying that you should actually use it)
- How does a function call work. Hint: stack, frames, return addresses,...
- What CPU-registers are there and what are they used for
- How is the FPU organized. Hint: register stack.
- How does the CPU cache work, what's branch prediction
- What are SIMD-instructions, what is memory alignment, SSE-intrinsics
- How does the compiler optimize your code
- How does multi-threading work on the CPU-level
This list is obviously incomplete, but probably a good start.
x = y >> 32;
??
My guess is that when they ask for low-level programming, they're talking about assembly. In a game development context, the only kind of assembly you're ever going to write is usually inline-assembly, so something like (stupid example):
float myFunc() { float abc = 1.3f; _asm { fld [abc] fsqrt }}Much more important than knowing the actual assembly instructions however is knowing about CPU architecture and data representation. That knowledge will also help you with writing more efficient high-level programs.
Things you should know:
- How are integers (signed and unsigned) represented in memory. Hint: twos-complement
- How are floats represented in memory. Hint: IEEE 754, mantissa, exponent...
- How is memory organized in general (code, stack, heap,...)
- How does memory allocation with new/malloc work
- How does alloca work (not saying that you should actually use it)
- How does a function call work. Hint: stack, frames, return addresses,...
- What CPU-registers are there and what are they used for
- How is the FPU organized. Hint: register stack.
- How does the CPU cache work, what's branch prediction
- What are SIMD-instructions, what is memory alignment, SSE-intrinsics
- How does the compiler optimize your code
- How does multi-threading work on the CPU-level
This list is obviously incomplete, but probably a good start.
So, I feel like maybe you've been given some bad advice in this thread. (Hopefully, I'm not about to add to it).
Low-level can either be used in reference to the language (i.e. C# as a high-level language vs. assembly as a low-level language), OR it can be used to refer to what types of systems are being programmed: i.e. device drivers are considered low-level programs (because they're less abstracted away from the hardware than a standard application). Aspects of an operating system (such as the memory allocation routines and various kernel components) are also considered low-level systems.
I believe, when it says a requirement is "low-level programming" it probably means something on the low-level system programming side of things, not necessarily using a low-level language. My theory is that if they wanted you to know an assembly language (there are several), they would have called out which one. Hence my conclusion that they are referring to low-level system programming, not the language being used.
Generally, low-level systems (i.e. drivers, as stated above) require the use of IO interfacing to "talk" directly to the hardware (things like using serial communication, ports, IRQs, communicating to the buses directly, etc), usually there are special low-level routines to be used (such as special kernel-side memory allocation routines, etc). Basically, you're talking straight to the hardware without the usual intermediaries (i.e. an application talks to the display via some sort of interface, like Direct3D or SetDisplayMode, where a display driver would be sending PCI (etc) bus messages directly).
Many drivers are written in C or C++, which are generally considered to be high-level languages (though I would argue that they have some low-level tendencies). I work on display drivers for Windows CE, and our code is pretty much all in C and C++, because CE supports a variety of processor types (x86, ARM, MIPS), and it's infeasible and unnecessary to write special assembly-language drivers for all of our devices.
I may be wrong, they may, in fact, be referring to low-level languages, but I don't believe this is the case.
A good starting point would be learning how something like a system memory allocator works - maybe write your own memory manager, something like that. Read in-depth into how modern kernels work - how they allocate memory, how drivers run, that sort of thing. I'm not really sure. The type of low-level programming required probably depends heavily on what the actual job would be - try to figure out what kinds of lower level systems would be in use with the job described, and do some research.
Good luck, and I hope that helps!
Low-level can either be used in reference to the language (i.e. C# as a high-level language vs. assembly as a low-level language), OR it can be used to refer to what types of systems are being programmed: i.e. device drivers are considered low-level programs (because they're less abstracted away from the hardware than a standard application). Aspects of an operating system (such as the memory allocation routines and various kernel components) are also considered low-level systems.
I believe, when it says a requirement is "low-level programming" it probably means something on the low-level system programming side of things, not necessarily using a low-level language. My theory is that if they wanted you to know an assembly language (there are several), they would have called out which one. Hence my conclusion that they are referring to low-level system programming, not the language being used.
Generally, low-level systems (i.e. drivers, as stated above) require the use of IO interfacing to "talk" directly to the hardware (things like using serial communication, ports, IRQs, communicating to the buses directly, etc), usually there are special low-level routines to be used (such as special kernel-side memory allocation routines, etc). Basically, you're talking straight to the hardware without the usual intermediaries (i.e. an application talks to the display via some sort of interface, like Direct3D or SetDisplayMode, where a display driver would be sending PCI (etc) bus messages directly).
Many drivers are written in C or C++, which are generally considered to be high-level languages (though I would argue that they have some low-level tendencies). I work on display drivers for Windows CE, and our code is pretty much all in C and C++, because CE supports a variety of processor types (x86, ARM, MIPS), and it's infeasible and unnecessary to write special assembly-language drivers for all of our devices.
I may be wrong, they may, in fact, be referring to low-level languages, but I don't believe this is the case.
A good starting point would be learning how something like a system memory allocator works - maybe write your own memory manager, something like that. Read in-depth into how modern kernels work - how they allocate memory, how drivers run, that sort of thing. I'm not really sure. The type of low-level programming required probably depends heavily on what the actual job would be - try to figure out what kinds of lower level systems would be in use with the job described, and do some research.
Good luck, and I hope that helps!
Quote:
Original post by JimmyDeemo
Ok so I’ve got my eye on a programming job, but it requires the candidate to have some experience with low level programming.
What i was wondering is, where does low level programming fit game programming as a whole? What situations would you apply low level programming and what are the benefits?
Hi,
I am by no means an expert in this sort of thing, but when I was doing my master thesis about computer graphics (not related to games, but I think the example still holds) there was a time when I started to use profilers to discover where most time was spent on the whole thing. I had a basic knowledge of assembly back then, but haven't really used it for years.
Anyway, the most used function I had was something called _ftol / _ftol2 being called about a few million times per frame. After a few googling arround, I discovered that this function was called everytime you made a cast from a floating type to an integer type (and there were a lot of them). Worst, I discovered that this function was also pretty damn slow because it seemed to imply that the CPU had to change it's rounding state, perform the rounding and then restore the CPU's normal state... and this had to be done eveytime you called the function. It seems that the C standard requires that these operations be done everytime you make a C cast.
After a few more diggings, I discovered some assembly alternatives to this, i.e, performing rounding without a call to _ftol. It was a question of a) not doing casts when I actually didn't need them and b) call these assembly alternatives when I had to.
I think that low level stuff such as assembly optimization may be kind of like this... applicable to very specific areas of the code where you know it makes a difference. But that is just my 5 cents... Like I said, I don't know much about it.
Anyway, maybe this link will help you get a more general idea about this stuff :
Michael Abrash on Pixomatic
It's about the work Michael Abrash has done on the Pixomatic software rasterizer.
Well the job posting is for a games company that product quite big games, for most platforms. So i guess your right in that they are probably looking for someone who knows what implications high-level code has at low-level and also how to improve that to make it more efficient. I read once about something to do with declaring structs, in that there is a way to make sure each members fall into even orderd bytes of memory, thus making it more efficient. I guess these are the kinda of issues i should be looking at.
Drilian, thanks for looking at it from a different angle, i think your thinking is more in the right direction.
Harry Hunt, i believe the first thing you wrote is the bit-shifting i meant. But i'm not sure about what it actually is, or how its used. I guess i've never programmed something thats needed it!?
Drilian, thanks for looking at it from a different angle, i think your thinking is more in the right direction.
Harry Hunt, i believe the first thing you wrote is the bit-shifting i meant. But i'm not sure about what it actually is, or how its used. I guess i've never programmed something thats needed it!?
maybe you should ask your friend or the company to get a better idea, because posting about what we think they mean is kind of useless
Well the job advert reads 'good knowledge of low-level programming' but i guess your right. Do you think i'd be making myself look inexperienced by asking and therefore giving them the impression i have know idea that i'm talking about?!
nope
Quote:
Original post by JimmyDeemo
Harry Hunt, i believe the first thing you wrote is the bit-shifting i meant. But i'm not sure about what it actually is, or how its used. I guess i've never programmed something thats needed it!?
Here's an example:
The number 87 in binary is 1010111
Now bit-shifting literally means shifting the bits. You can shift bits to the left by appending a zero or you can shift to the right by dropping the last bit.
1010111 << 1 = 10101110 = 174 = 87 * 2
1010111 >> 1 = 101011 = 43 = 87 / 2
As you can see shifting one bit to the left is the same as multiplying by two while shifting one bit to the right is the same as dividing by two. Bit-shifting can be used as a replacement for all power-of-two integer multiplications/divisions and at least on x86, it tends to be much faster (SHL ~2 CPU cycles, MUL ~50 CPU cycles).
Quote:
Original post by mastersmithbut be warned if your going to mess with assembler, back up your hd, because you are working with the memory and cpu at the lowest levels you can really mess up your computer.
No you can't. Working with assembly is no more risky than working with any other language. All languages run as machine code on the actual computer anyway, the only difference is how you get there.
I'd suggest wolverine is on the right track. A games posting asking for low-level experience is generally going to be after someone who knows how things work at the assembly level with an eye to optimization (since there's really nothing else you'd use asm for in games). Things like cache misses, pipeline stalls, the good old _fotl issue, SSE (if you're working on intel) and so on. Being able to use a profiler would also be an essential skill.
Also this may seem a little harsh, but I'd say if you're unfamiliar with bit shifts that you lack the knowledge they're after for such a position.
Quote:
Original post by Harry HuntAs you can see shifting one bit to the left is the same as multiplying by two while shifting one bit to the right is the same as dividing by two. Bit-shifting can be used as a replacement for all power-of-two integer multiplications/divisions and at least on x86, it tends to be much faster (SHL ~2 CPU cycles, MUL ~50 CPU cycles).
More like 1 vs 5-15 on modern CPUs. Also AMDs are somewhat faster at multiplies than intel since they have a dedicated integer multiplier, while Intels use the fpu.
Fair comment Jerax, i've done a degree in Games Computing and worked as a software engineer for a year, i just don't seem to have come across bit shifting. I understand that i might not have the knowledge but that part of the reason why i'm asking about this. Guess i've got a lot more to learn before i can move jobs.
bit shifting as already explained is shifting the bits in a binary number either to the left or to the right. Sometimes it's used to multiply or divide quickly. You can do shifts in either assembler or C++ infact you can do it in most languages.
To learn about how this sort of stuff works you need to look up binary and hex maths and converting between different number bases.
Knowing this sort of low level number manipulation is probably what they expect you to know. Once you know how the bits are manipulated inside a computer learning assembly for a particular computer shouldn't prove impossible.
To learn about how this sort of stuff works you need to look up binary and hex maths and converting between different number bases.
Knowing this sort of low level number manipulation is probably what they expect you to know. Once you know how the bits are manipulated inside a computer learning assembly for a particular computer shouldn't prove impossible.
Low level programming means being familiar with how things work under the hood.
How is memory managed under the compiler? Under the OS? On the hardware?
How is IO managed under the hood? How is async IO handled?
How do function calls work? What are calling conventions? What are the penalties for using them?
What is data alignment? Why does it matter? Why doesn't it? How to bypass it? How to make good use of it and when?
What are the costs of threads? Which penalties you can't get away from, which can you avoid?
How to program for cache efficiency? How to organize code to make use of as many cache levels as possible? Which algorithms and techniques are cache friendly, which aren't?
For 3D cards - where does the cost of operations come from? How to batch data and why? Which hardware factors affect these decisions?
Why is STL "slow"? Why is STL "fast"? How can you go from slow to fast?
And much more...
Then demonstrate how you solved these problems, or how you'd address the short-comings you list above, as well as the trade-offs you impose this way.
Today, you don't really need to worry about any of those, frameworks, toolkits, compilers and OS will take care of it. But if you know the tiny details underneath, you can push the performance far beyond what is obvious at algorithmic level.
And assembly is only a minor part in this. It's not really that useful, with exception of SIMD concepts, which require parallel algorithm design in the first place, so they fall under algorithmic optimization.
How is memory managed under the compiler? Under the OS? On the hardware?
How is IO managed under the hood? How is async IO handled?
How do function calls work? What are calling conventions? What are the penalties for using them?
What is data alignment? Why does it matter? Why doesn't it? How to bypass it? How to make good use of it and when?
What are the costs of threads? Which penalties you can't get away from, which can you avoid?
How to program for cache efficiency? How to organize code to make use of as many cache levels as possible? Which algorithms and techniques are cache friendly, which aren't?
For 3D cards - where does the cost of operations come from? How to batch data and why? Which hardware factors affect these decisions?
Why is STL "slow"? Why is STL "fast"? How can you go from slow to fast?
And much more...
Then demonstrate how you solved these problems, or how you'd address the short-comings you list above, as well as the trade-offs you impose this way.
Today, you don't really need to worry about any of those, frameworks, toolkits, compilers and OS will take care of it. But if you know the tiny details underneath, you can push the performance far beyond what is obvious at algorithmic level.
And assembly is only a minor part in this. It's not really that useful, with exception of SIMD concepts, which require parallel algorithm design in the first place, so they fall under algorithmic optimization.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement