View Full Version : Yet another (Open Source) H264 decoder
ludrao
1st August 2009, 13:27
Hi all, I am not sure this is the right section to post this news, but anyway here it is:
I just released an H264 video decoder under open source terms. It was designed with multi-threading in mind. The performances are not that tremendous (yet) but I did not do any optimization pass (yet).
I would like to have more feedbacks before I continue spending a lot of time on this wonderful project :thanks:.
www.ludrao.net/ludh264
shon3i
1st August 2009, 15:42
First thanks for your hard work :), second can you compile binary (.ax) so we can make test's.
tetsuo55
1st August 2009, 16:08
Hi ludrao,
Thanks for making an open source h264 decoder, designed from the ground up to be fast.
How did you thread the decoder?
I ask this because i want to know if its possible to add hardware acceleration to the decoder.
things like DXVA use a 4 step system to decode h264, is your decoder threaded in the same way?
Would it be possible to give any of the 4 steps to the videocard, and let the cpu decode the others?
ludrao
1st August 2009, 17:35
First thanks for your hard work :), second can you compile binary (.ax) so we can make test's.
Well I do provide a binary, but it is only a command line executable for Linux 64bits. That's a bit restrictive, I agree. However the source is available and I'll provide support if anybody is interested to write a filter or integrate it into any player/library.
Also the performances are not that good, as I stated before. It is more in a development state than a production state.
ludrao
1st August 2009, 17:44
How did you thread the decoder?
I wanted to enable frame/mb decoding threading. The syntax decoding (including CABAC/CAVLC) is not multi threaded in itself
things like DXVA use a 4 step system to decode h264, is your decoder threaded in the same way?
Would it be possible to give any of the 4 steps to the videocard, and let the cpu decode the others?
I actually do not know DXVA:rolleyes:.
The threading is actually done in the following way: There is one thread that do the syntax decoding, and stack up the actual video decoding and filtering. Then I tried different strategies to do the video decoding: mb-based multithreading spanning on several frames, mb-base multithreading with mb of the same frame, and then frame(slice)-base multithreading.
In ludh264, implementing a new threading stategy is quite simple: only need to implement one file.
Dark Shikari
1st August 2009, 20:03
static should_inline void renormalization_process(CABACContext* cabac_ctx, BitStreamContext* bs)
{
while (cabac_ctx->codIRange < 0x0100)
{
cabac_ctx->codIRange = cabac_ctx->codIRange << 1;
cabac_ctx->codIOffset = cabac_ctx->codIOffset << 1 | bs_read_u1(bs);
// cubu debug
CABAC_DEBUG("%d", cabac_ctx->codIOffset & 1);
}
}
Oh dear, a bit-at-a-time arithmetic decoder. This is going to be sloooow.
ludrao
1st August 2009, 21:10
Oh dear, a bit-at-a-time arithmetic decoder. This is going to be sloooow.
Right, as I said I did not do optimization pass. CABAC would a first step :). Also I should precise that this is all implemented in C, no asm. Actually, in order to test, I did implement some functions in asm (sse2) but they are not used by default.
My first goals were to:
make an h264 decoder that actually decode h264
make it easily multithreadable
I believe that I reached those 2 goals, but there is still a long run before having a production proof codec ;-)
Revgen
1st August 2009, 21:59
^You might want to ask a mod move this to the H264 section. You'll get more visitors. I'll check it out later.
_xxl
2nd August 2009, 14:47
Your download link doesn't work.
ludrao
3rd August 2009, 20:24
Your download link doesn't work.
Yurk. Which one ?
popper
4th August 2009, 01:13
Right, as I said I did not do optimization pass. CABAC would a first step :). Also I should precise that this is all implemented in C, no asm. Actually, in order to test, I did implement some functions in asm (sse2) but they are not used by default.
My first goals were to:
make an h264 decoder that actually decode h264
make it easily multithreadable
I believe that I reached those 2 goals, but there is still a long run before having a production proof codec ;-)
i wonder , rather than you reinventing the wheel yet again, you might look at using the existing SIMD optimised Eigen2 code in parts of your rewrite optimisations later.
http://eigen.tuxfamily.org/dox/InsideEigenExample.html
http://eigen.tuxfamily.org/index.php?title=Benchmark
http://bjacob.livejournal.com/
http://forum.kde.org/viewforum.php?f=74
something to look at anyway if you intent this to become usable in a fast code sense.
Porting optimized assembly routines from libavcodec and x264 (and perhaps disassemblies of commercial codecs) would be more useful than calling generic SIMD libraries though.
popper
4th August 2009, 10:46
true for a one off project it may be werth pulling selective bits of code from here and there as required ,but if you take the wider aproach and design in for these active and ever improving SIMD 3rd party libs from the start , every time they improve a routine and put out the updated lib, you get a boost from that one place.... no more selective hunting down that new code snippet that gives you a 4% increase in speed etc every single time it changes, makeing it fit in your project yet again, and then compiling a new version to put out.
he also implyed he likes prototyping in C code, and so he gets that, and ready made fast C (cross platform) SIMD routines to try with something like that open Eigen2 from every project he uses it with.
plus OC they seem perfectly happy to take new problems and write Vectorization code to solve a given problem, refactor it for fun and get the most out of it, and add it into the core, so thats a good thing, they do what they are good and happy at doing, you supply the interesting problems you want made faster to them, and get on with your projects and feed it back, everyone wins.
Dark Shikari
4th August 2009, 18:24
true for a one off project it may be werth pulling selective bits of code from here and there as required ,but if you take the wider aproach and design in for these active and ever improving SIMD 3rd party libs from the start , every time they improve a routine and put out the updated lib, you get a boost from that one place.... no more selective hunting down that new code snippet that gives you a 4% increase in speed etc every single time it changes, makeing it fit in your project yet again, and then compiling a new version to put out.Generic SIMD code will always be significantly slower than code that's actually optimized by a real person.
popper
4th August 2009, 20:30
Generic SIMD code will always be significantly slower than code that's actually optimized by a real person.
indeed, and these guys working on the likes of Eigen2 and writeing their hand written , refactoring it for fun and to get the most out of the given routines are real people we assume ;)
not a subset of GCC auto vectorisation. :(
its clear some people are not as good at Vectorizing code (if they even try) as you Dark Shikari, so these evolving 3rd party SIMD librarys should be a very good thing for the average new dev's starting out on new projects, and be encurraged to be included generally should they not ?
actually now you mention it, perhaps all the hand written general routine Vectorization code from libavcodec and x264 could be condensed down into a compact version and find its way into the likes of Eigen2 so devs can more easly use them any time they start a new project such as this YAOSHD [Yet another (Open Source) H264 decoder] .
infact over time if the will were there ,it may be possible to pair this down to such a degree so that all the video projects can mearly plug in a selection of the external SIMD routines to get a given input/ouput outcome, a far finer grained version of what happens now.
someone wants a SIMD CABAC/CAVLC function, dont pull the latest abstract code from x264 , tap into the evolving SIMD libarys version that you ported there, and someone else hand optimised it even more later.... or use the one were someone else took a totally different Algorithm and did the same thing another way as it gives them something extra....and all the other options you could brake down in to totally seperate fully working related routines...as an example.
Dark Shikari
4th August 2009, 20:34
indeed, and these guys working on the likes of Eigen2 and writeing their hand written Vectorization code, refactoring it for fun and to get the most out of the given routines are real people we assume ;)
not a subset of GCC auto vectorisation. :(By that absurd logic, if I write a compiler, said compiler will be able to generate assembly as good as if I wrote the assembly code myself. If you don't see why this logic is ridiculous, you probably shouldn't be talking about compilers.its clear some people are not as good at Vectorizing code (if they even try) as you Dark Shikari, so these evolving 3rd party SIMD librarys should be a very good thing for the average new dev's starting out on new projects, and be encurraged to be included generally should they not ?No, they should be encouraged to use something widely-supported like nasm-syntax assembly rather than relying on a special compiler which may stop being developed tomorrow for all we know.
No language or file format which has only one implementation should ever be used for any serious purpose.
ludrao
4th August 2009, 20:49
Thank you all for your tips I'll have a look. It looks like there may be a troll trying to sniff in this thread, if you see him squeeze him please !
Dark Shikari, you seems to be really experienced with SIMD stuff. Would you recommand a good document for writing good SIMD code. I am particularly un-experienced with the cacheline things ;-)
For those whom be interested I added x86 (32bits) binaries in the download page. I hope a windows binary will make it through soon !
Dark Shikari
4th August 2009, 20:53
Thank you all for your tips I'll have a look. It looks like there may be a troll trying to sniff in this thread, if you see him squeeze him please !He does have a point; arch-independent SIMD libraries are a nice time-saver if you care about performance on a lot of platforms and you can't afford the time to do it right for any individual one. But if you only care about x86, you might as well do it right the first time.Dark Shikari, you seems to be really experienced with SIMD stuff. Would you recommand a good document for writing good SIMD code. I am particularly un-experienced with the cacheline things ;-)
Read everything here (1-3 at least): http://www.agner.org/optimize/
The instruction tables are a good reference you should always keep around, as is the NASM manual (http://alien.dowling.edu/~rohit/nasmdocb.html).
The official Intel/AMD architecture manuals are also quite useful. And of course one of the best ways to learn is to look at existing good code and learn how it works and why it is good, asking questions as necessary (#x264dev on IRC is always a good place) to learn what you can't figure out from inspection.
Cacheline stuff falls into the category of "very architecture-specific dirty tricks," along with stuff like "using pmaddubsw to subtract numbers."
popper
4th August 2009, 21:07
"Quote:
Originally Posted by popper
indeed, and these guys working on the likes of Eigen2 and writeing their hand written Vectorization code, refactoring it for fun and to get the most out of the given routines are real people we assume
not a subset of GCC auto vectorisation.
"
By that absurd logic, if I write a compiler, said compiler will be able to generate assembly as good as if I wrote the assembly code myself. If you don't see why this logic is ridiculous, you probably shouldn't be talking about compilers.No, they should be encouraged to use something widely-supported like nasm-syntax assembly rather than relying on a special compiler which may stop being developed tomorrow for all we know.
No language or file format which has only one implementation should ever be used for any serious purpose.
What? how did you get from my "they are real people" " they are NOT a subset of GCC auto vectorisation"
to your "absurd logic" comment, the total opposite of what i said, to be clear they are real people so they CAN and DO hand optimise their code just as you said above :confused:
OF course its clear "said compiler will [NOT] be able to generate assembly as good as if I wrote the assembly code myself." thats Obvious and NOTHING like i said or implyed.
moving on, we all know you Really LIKE your assembly code and advocate everyone use it were they can, and thats one POV, but my main point is, many people dont feel comfortable there, so a C library option is always a better option than nothing
popper
4th August 2009, 21:23
Thank you all for your tips I'll have a look. It looks like there may be a troll trying to sniff in this thread, if you see him squeeze him please !
Dark Shikari, you seems to be really experienced with SIMD stuff. Would you recommand a good document for writing good SIMD code. I am particularly un-experienced with the cacheline things ;-)
For those whom be interested I added x86 (32bits) binaries in the download page. I hope a windows binary will make it through soon !
Oh dont be a suckup, sure Dark Shikari knows his stuff, and you will more than likely learn a LOT of interesting options and ways to optimise your code over time looking at his code,but dont go implying people are trolls until you have got a few years posting here.
its also interesting how this implyed troll is the one that got you actually thinking about SIMD, and so asked dark Shikari for any SIMD tips, something you clearly had not even considered for your APP before the posts looking at your code i might add ;)
if you dont want to look at the links provided and judge them on their own merits thats your luck out you could have learned so much more.
akupenguin
5th August 2009, 01:35
AFAICT Eigen2 doesn't support int8 or int16 math at all, which entirely rules it out for video codec use. However many applications may use int32, float, double, and complex, that doesn't include us.
ludrao
5th August 2009, 18:45
but dont go implying people are trolls until you have got a few years posting here.
I got misunderstood ;-). I did not imply somebody is a troll. The troll was more a concept: manually written SIMD is better/worse than using libraries that does it for you automatically.
Clearly the pro of libraries: portability and ease of use
Clearly the pro of manual SIMD: optimization exactly up to a single instruction granularity to exactly fit your needs.
I actually like both approach, that's why I will, as I said look into ALL your tips. Thanks again.
its also interesting how this implyed troll is the one that got you actually thinking about SIMD, and so asked dark Shikari for any SIMD tips, something you clearly had not even considered for your APP before the posts looking at your code i might add ;)
I actually did think about SIMD instructions AND libraries before posting here ;-) Have a look at motion_compensation_sse2.c file. (I must tell that ffmpeg did inspire me a lot for this code...)
At the begining I wanted to use gcc intrisics and looked for something more portable and easier to use than raw assembly, but then I got caught by ffmpeg assembly code and tried it. It is fun, but it takes a LOT of time...
if you dont want to look at the links provided and judge them on their own merits thats your luck out you could have learned so much more.
I will look at the links, I actually already did as soon as you posted them! I am confident that I will explore it more to undestand if this is what I am looking for. I agree 100% with you about the merit and everything ;-)
ludrao
5th August 2009, 18:48
Oh I forgot, I LOVE trolls and often try to spawn some small ones. (when they allow people to give their thought)
popper
6th August 2009, 02:22
;)
moving on , purely from a practical POV these routines may be of use or instuctive to someone!
http://graphics.stanford.edu/~seander/bithacks.html
"
Bit Twiddling Hacks
By Sean Eron Anderson
Individually, the code snippets here are in the public domain (unless otherwise noted) — feel free to use them however you please.
The aggregate collection and descriptions are © 1997-2005 Sean Eron Anderson.
The code and descriptions are distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY and without even the implied warranty of merchantability or fitness for a particular purpose.
As of May 5, 2005, all the code has been tested thoroughly.
Thousands of people have read it. Moreover, Professor Randal Bryant, the Dean of Computer Science at Carnegie Mellon University, has personally tested almost everything with his Uclid code verification system. What he hasn't tested, I have checked against all possible inputs on a 32-bit machine.
To the first person to inform me of a legitimate bug in the code, I'll pay a bounty of US$10 (by check or Paypal). If directed to a charity, I'll pay US$20.
Contents ...!
About the operation counting methodology
Compute the sign of an integer
Compute the integer absolute value (abs) without branching
Compute the minimum (min) or maximum (max) of two integers without branching
Determining if an integer is a power of 2
Sign extending
Sign extending from a constant bit width
Sign extending from a variable bit-width
Sign extending from a variable bit-width in 3 operations
Conditionally set or clear bits without branching
Conditionally negate a value without branching
Merge bits from two values according to a mask
Counting bits set
Counting bits set, naive way
Counting bits set by lookup table
Counting bits set, Brian Kernighan's way
Counting bits set in 12, 24, or 32-bit words using 64-bit instructions
Counting bits set, in parallel
Computing parity (1 if an odd number of bits set, 0 otherwise)
Compute parity of a word the naive way
Compute parity by lookup table
Compute parity of a byte using 64-bit multiply and modulus division
Compute parity of word with a multiply
Compute parity in parallel
Swapping Values
Swapping values with subtraction and addition
Swapping values with XOR
Swapping individual bits with XOR
Reversing bit sequences
Reverse bits the obvious way
Reverse bits in word by lookup table
Reverse the bits in a byte with 3 operations (64-bit muliply and modulus division)
Reverse the bits in a byte with 4 operations (64-bit multiply, no division)
Reverse the bits in a byte with 7 operations (no 64-bit, only 32)
Reverse an N-bit quantity in parallel with 5 * lg(N) operations
Modulus division (aka computing remainders)
Computing modulus division by 1 << s without a division operation (obvious)
Computing modulus division by (1 << s) - 1 without a division operation
Computing modulus division by (1 << s) - 1 in parallel without a division operation
Finding integer log base 2 of an integer (aka the position of the highest bit set)
Find the log base 2 of an integer with the MSB N set in O(N) operations (the obvious way)
Find the integer log base 2 of an integer with an 64-bit IEEE float
Find the log base 2 of an integer with a lookup table
Find the log base 2 of an N-bit integer in O(lg(N)) operations
Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup
Find integer log base 10 of an integer
Find integer log base 10 of an integer the obvious way
Find integer log base 2 of a 32-bit IEEE float
Find integer log base 2 of the pow(2, r)-root of a 32-bit IEEE float (for unsigned integer r)
Counting consecutive trailing zero bits (or finding bit indices)
Count the consecutive zero bits (trailing) on the right linearly
Count the consecutive zero bits (trailing) on the right in parallel
Count the consecutive zero bits (trailing) on the right by binary search
Count the consecutive zero bits (trailing) on the right by casting to a float
Count the consecutive zero bits (trailing) on the right with modulus division and lookup
Count the consecutive zero bits (trailing) on the right with multiply and lookup
Round up to the next highest power of 2 by float casting
Round up to the next highest power of 2
Interleaving bits (aka computing Morton Numbers)
Interleave bits the obvious way
Interleave bits by table lookup
Interleave bits with 64-bit multiply
Interleave bits by Binary Magic Numbers
Testing for ranges of bytes in a word (and counting occurances found)
Determine if a word has a zero byte
Determine if a word has byte less than n
Determine if a word has a byte greater than n
Determine if a word has a byte between m and n
"
http://www.codex.gr/system/files/SoftwareOptimizations.pdf
a very,very basic overview but perhaps interesting to some.
Dark Shikari
6th August 2009, 02:28
Most of those aren't very useful, though some are interesting to have around (though I recall a few aren't very optimal...)
SWAR stuff is much more interesting IMO.
popper
6th August 2009, 20:35
Most of those aren't very useful, though some are interesting to have around (though I recall a few aren't very optimal...)
SWAR stuff is much more interesting IMO.
ohh right :helpful: SWAR (Swara) - Notes of the Indian Scale ;)
http://chandrakantha.com/articles/indian_music/swar.html
"Swar are nothing more than the seven notes of the Indian musical scale...."
you mean this ;)
i had not seen that acronym since the CATS (Commodore Amiga Technical Support.) days
http://cobweb.ecn.purdue.edu/~hankd/SWAR/over.html
Technical Summary: SWAR Technology
February 4, 1997, by Hank Dietz
http://cobweb.ecn.purdue.edu/~hankd/SWAR/
SWAR: SIMD Within A Register
SIMD (Single Instruction stream, Multiple Data stream) Within A Register (SWAR) isn't a new idea.
Given a machine with k-bit registers, data paths, and function units, it has long been known that ordinary register operations can function as SIMD parallel operations on n k/n-bit field values.
For example, a fast population count (number of 1 bits) operation is often implemented using a SWAR reduction algorthm.
A larger example is in the 1992 PhD thesis of (my former student) M. Liou, Efficient Algorithms for Fractional Factorial Design Generation, which made extensive use of SWAR techniques to speed-up a class of optimization algorithms... but even that was obscure stuff.
Now, multimedia applications are anything but obscure, and SWAR techniques can easily yield 2x to 8x speedup. Recognizing this, the 1997 versions of most microprocessors will incorporate hardware support for SWAR:
http://www.aggregate.org/SWAR/
http://www.aggregate.org/SWAR/Swarc/Scc.html
The SWARC Language
The SWARC Compiler, Scc
Dark Shikari
6th August 2009, 20:41
i had not seen that acronym since the CATS (Commodore Amiga Technical Support.) daysAlso see this (http://guru.multimedia.cx/simd-without-simd/).
ludrao
7th August 2009, 21:52
I managed to compile binaries for windows. They are available here: http://www.ludrao.net/home/ludh264/download.
I "tested" on a virtual machine, and it was terribly slow (probably due to the lack of video acceleration support?). Anyway, it was faster when run with wine on Linux. If somebody could test them on a real Windows machine, that would be cool ;-)
popper
8th August 2009, 01:53
which virtual machine did you try ?, virtual box that happens to be the best cross platform VM right now IMO now has experimental DirectX 8/9
not tryed it with your binarys but werth a try for getting better throughput perhaps...
http://www.virtualbox.org/
http://www.virtualbox.org/manual/UserManual.html#guestadd-3d
"....
The 3D acceleration currently has the following preconditions:
It is only available for certain Windows, Linux and Solaris guests. In particular:
For Windows guests, support is restricted to 32-bit versions of XP and Vista. Both OpenGL and DirectX 8/9 are supported (experimental).
OpenGL on Linux requires kernel 2.6.27 and higher as well as X.org server version 1.5 and higher. Ubuntu 8.10 and Fedora 10 have been tested and confirmed as working.
OpenGL on Solaris guests requires X.org server version 1.5 and higher.
The Guest Additions must be installed.
Note
For Direct 3D acceleration to work in a Windows Guest, VirtualBox needs to replace Windows system files in the virtual machine. As a result, the Guest Additions installation program offers Direct 3D acceleration as an option that must be explicitly enabled.
Also, you must install the Guest Additions in "Safe Mode"; see Chapter 13, Known limitations for details.
Because 3D support is still experimental at this time, it is disabled by default and must be manually enabled in the VM settings (see the section called “General settings”).
Technically, VirtualBox implements this by installing an additional hardware 3D driver inside your guest when the Guest Additions are installed.
This driver acts as a hardware 3D driver and reports to the guest operating system that the (virtual) hardware is capable of 3D hardware acceleration.
When an application in the guest then requests hardware acceleration through the OpenGL or Direct3D programming interfaces, these are sent to the host through a special communication tunnel implemented by VirtualBox, and then the host performs the requested 3D operation via the host's programming interfaces.
..."
ludrao
14th September 2009, 21:55
static should_inline void renormalization_process(CABACContext* cabac_ctx, BitStreamContext* bs)
{
while (cabac_ctx->codIRange < 0x0100)
{
cabac_ctx->codIRange = cabac_ctx->codIRange << 1;
cabac_ctx->codIOffset = cabac_ctx->codIOffset << 1 | bs_read_u1(bs);
// cubu debug
CABAC_DEBUG("%d", cabac_ctx->codIOffset & 1);
}
}
Oh dear, a bit-at-a-time arithmetic decoder. This is going to be sloooow.
I did some tests and changed the "read one bit at a time" with a preload buffer so that its read several bytes at a time instead (took some idea from ffmpeg - thanks). The improvement is actually quite small ;-).
I do not actually really get why the increase of speed is so small. Maybe it comes from the fact that this preload buffer stuff add a test (that can be mispredicted) (if needtorefill buffer ...)
I also did some other test like branchless code for the refill/decode_cabac_1bit but it was actually slower !
This was actually just for fun, I guess that I now need to do real profiling of the codec and see where the CPU is spent.
Dark Shikari
14th September 2009, 22:56
I did some tests and changed the "read one bit at a time" with a preload buffer so that its read several bytes at a time instead (took some idea from ffmpeg - thanks). The improvement is actually quite small ;-).
I do not actually really get why the increase of speed is so small. Maybe it comes from the fact that this preload buffer stuff add a test (that can be mispredicted) (if needtorefill buffer ...)
I also did some other test like branchless code for the refill/decode_cabac_1bit but it was actually slower !
This was actually just for fun, I guess that I now need to do real profiling of the codec and see where the CPU is spent.Branchless refilling is probably slower, but if you only refill every 16 bits, that's one misprediction every ~20 CABAC decodes, i.e. nearly nothing.
Making everything other than refilling branchless, however, is generally a good idea.
ludrao
15th September 2009, 20:17
Yeah I would expect that you are right, however the simple benchmark does not prove it. I removed the image decoding and only do the syntax parsing using cabac. I took a long h264 stream that take about 30 seconds to decode. I measured the time of execution of the decode_cabac_1bit function with the branchless code and the one with the branching code. The measured difference is less than 200ms out of 30s !
You can have a look to my branchless (https://svn.ludrao.net/ludsource/ludh264/cabac.h) code, nothing fancy.
Dark Shikari
15th September 2009, 20:28
int shift = 8-im_log2_9b(cabac_ctx->codIRange >> BUFFER_BITS);I don't see this function. It should be a lookup table, not a function. The measured difference is less than 200ms out of 30s !With your DSP functions nearly completely unoptimized, this isn't surprising; their time will swamp CABAC until you write SIMD for them.
ludrao
15th September 2009, 20:42
I don't see this function. It should be a lookup table, not a function.
It is ;-). It's defined as an inlined function here (https://svn.ludrao.net/ludsource/ludh264/intmath.h):
With your DSP functions nearly completely unoptimized, this isn't surprising; their time will swamp CABAC until you write SIMD for them.
What do you mean by DSP functions ? The ones for image decoding ? If yes, that's exactly why I disabled. For the above benchmark I did not decode the image, only the syntax elements.
Out of curiosity, what do you use for profiling ? I am quite found of valgrind, but I looks like it is not that realistic, I guess because of the caching of there "Virtual CPU" that is quite different of the caching of the real CPU. I am not sure though.
The other method I did, is just to measure the time of execution on the same stream. At least it gives a comparison.
Dark Shikari
15th September 2009, 20:45
What do you mean by DSP functions ? The ones for image decoding ? If yes, that's exactly why I disabled. For the above benchmark I did not decode the image, only the syntax elements.Ah, I missed that part when reading. By DSP functions I mean iDCT, MC, intra prediction, and deblocking.Out of curiosity, what do you use for profiling ? I am quite found of valgrind, but I looks like it is not that realistic, I guess because of the caching of there "Virtual CPU" that is quite different of the caching of the real CPU. I am not sure though.oprofile is amazing and you should use it. Valgrind's good for finding bugs, not so much for profiling.
akupenguin
15th September 2009, 22:42
I am quite found of valgrind, but I looks like it is not that realistic, I guess because of the caching of there "Virtual CPU" that is quite different of the caching of the real CPU.
Valgrind's cache model isn't too bad, the only major difference is that it doesn't prefetch. The main problem is that valgrind counts instructions, not cycles. It has no model of arithmetic latency/throughput.
ludrao
24th September 2009, 21:08
Valgrind's cache model isn't too bad, the only major difference is that it doesn't prefetch. The main problem is that valgrind counts instructions, not cycles. It has no model of arithmetic latency/throughput.
Which is a pity because coupled to kcachegrind it is wonderfully powerfull and easy to use ;-)
I am trying to use oprofile, but I am facing weird results:
opreport -lg ./ludh264
warning: /no-vmlinux could not be found.
warning: [vdso] (tgid:8618 range:0x7ffff0dfe000-0x7ffff0dff000) could not be found.
CPU: Core 2, speed 2003 MHz (estimated)
Counted BR_MISS_PRED_RETIRED events (number of mispredicted branches retired (precise)) with a unit mask of 0x00 (No unit mask) count 1001500
Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
samples % samples % linenr info image name symbol name
324 52.4272 199483 23.7715 decode_slice.c:1733 ludh264 residual
191 30.9061 369832 44.0713 cabac.h:193 ludh264 decode_cabac_1bit
28 4.5307 18670 2.2248 decode_slice.c:876 ludh264 mb_pred
15 2.4272 6669 0.7947 cabac.h:824 ludh264 cabac_decode_coeff_abs_level_minus1
11 1.7799 33743 4.0210 decode_slice.c:2066 ludh264 decode_macroblock_layer
10 1.6181 36939 4.4019 decode_slice.c:2371 ludh264 decode_slice_data_internal
9 1.4563 10548 1.2570 cabac.h:689 ludh264 cabac_decode_mvd_lX
The results seems to show that there a lot of branch mispred into decode_cabac_1bit. However I did the benchmark with a branchless version of the cabac engine. The only one test is the need to refill test.
When I run opannotate it gives me mispred on mov of neg instruction ??
:static should_inline unsigned int decode_cabac_1bit(CABACContext* cabac_ctx, BitStreamContext* bs, uint8_t* state_vars)
:{
116 18.7702 23695 2.8236 : 41f0c0: push %rbp
: unsigned int pStateIdx = (*state_vars) >> 1;
: unsigned int binVal;
: unsigned int qCodIRangeIdx = (cabac_ctx->codIRange >> (6+BUFFER_BITS)) & 3;
: cabac_reg codIRangeLPS = (cabac_reg)rangeTabLPS[pStateIdx][qCodIRangeIdx] << BUFFER_BITS;
0 0 246 0.0293 : 41f0c1: movzbl (%rdx),%eax
://
:// return binVal;
://}
:// Branchless code is not faster !
:static should_inline unsigned int decode_cabac_1bit(CABACContext* cabac_ctx, BitStreamContext* bs, uint8_t* state_vars)
:{
0 0 3272 0.3899 : 41f0c4: mov %rdi,%r9
: unsigned int pStateIdx = (*state_vars) >> 1;
: unsigned int binVal;
: unsigned int qCodIRangeIdx = (cabac_ctx->codIRange >> (6+BUFFER_BITS)) & 3;
: 41f0c7: mov (%rdi),%r8
: cabac_reg codIRangeLPS = (cabac_reg)rangeTabLPS[pStateIdx][qCodIRangeIdx] << BUFFER_BITS;
: cabac_ctx->codIRange -= codIRangeLPS;
:
: cabac_reg mask = (long)(cabac_ctx->codIRange - cabac_ctx->codIOffset-1) >> (sizeof(cabac_reg)*8-1);
28 4.5307 7636 0.9099 : 41f0ca: mov 0x8(%rdi),%rdi
://
:// return binVal;
://}
:// Branchless code is not faster !
:static should_inline unsigned int decode_cabac_1bit(CABACContext* cabac_ctx, BitStreamContext* bs, uint8_t* state_vars)
:{
0 0 1577 0.1879 : 41f0ce: mov %rsp,%rbp
: unsigned int pStateIdx = (*state_vars) >> 1;
: unsigned int binVal;
: unsigned int qCodIRangeIdx = (cabac_ctx->codIRange >> (6+BUFFER_BITS)) & 3;
: cabac_reg codIRangeLPS = (cabac_reg)rangeTabLPS[pStateIdx][qCodIRangeIdx] << BUFFER_BITS;
0 0 2256 0.2688 : 41f0d1: mov %r8,%rcx
0 0 6518 0.7767 : 41f0d4: shr %al
0 0 1607 0.1915 : 41f0d6: shr $0x36,%rcx
1 0.1618 2306 0.2748 : 41f0da: movzbl %al,%eax
0 0 1505 0.1793 : 41f0dd: and $0x3,%ecx
0 0 6865 0.8181 : 41f0e0: movzbl 0x4744c0(%rcx,%rax,4),%eax
: cabac_ctx->codIRange -= codIRangeLPS;
Does anybody have an idea ?
(I can give more dissambly/annotation but I did not this post to be flowed with big listings ;-) )
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.