View Full Version : Koepi vs personal build
plugh
19th April 2007, 22:22
I had noted in the past that Koepi's build of 1.1.2 was bigger than my builds.
For example, xvidcore.dll - Koepi 748KB - mine 588KB
I just chalked it up to differant compilers but assumed the output was the same.
I don't normally muck around with the core (my interest has been the 2nd pass vbv stuff, which I moved to vfw.dll) so I normally use Koepi's core.dll, but I was just trying an experiment and discovered that my assumption was incorrect. For the same clip and encoder options I get somewhat differant output files depending upon which xvidcore build I use.
Which begs the questions:
Which one is 'right'?
How do I determine that?
If mine is 'wrong' how do I fix it?
I've been using the visual studio workspace/project files included with the xvid source kit. I'm using MS Visual Studio 6 with Service Pack 5, Processor Pack 5, and nasm 0.98.39. I was under the impression this was a 'correct' setup. I have noted that do I get an error about an unknown compiler option 'Qipo' but as I understand it that is an option used by the Intel C compiler, not the MS one, and is harmless - perhaps not?
Suggestions?
Dark Shikari
20th April 2007, 00:27
He's probably using more aggressive optimization options. In GCC land, that might be -O3 and -funroll-loops that would increase the size as such.
plugh
20th April 2007, 01:58
Yeah, I figure he's using a differant compiler and/or options.
The significant point is that the results are differant as well.
As a first take, I diff'd the .pass files for my 7800 frame clip. These were both "full quality" first passes (not using the fast approx routines).
There are no differences in I frames (interval 240), scattered differences in isolated b-frames, and two segments with runs of differant p and b frames - one 198 frames long, the other 210 frames long. For example: ( <! is Koepi, !> is mine )
<! b 3 0 2560 0 4104 2879
!> b 3 0 2560 0 4106 2900
<! b 3 0 2560 0 5498 4357
!> b 3 0 2560 0 5471 4337
<! b 3 0 2560 0 15629 7732
!> b 3 0 2560 0 15652 7742
<! b 3 0 2560 0 13280 6691
!> b 3 0 2560 0 13280 6690
<! b 3 0 2560 0 7909 5051
!> b 3 0 2560 0 7907 5048
<! b 3 0 2560 0 10205 5730
!> b 3 0 2560 0 10211 5734
<! b 3 0 2560 0 11031 5689
!> b 3 0 2560 0 11034 5682
<! b 3 0 2560 0 4950 2688
!> b 3 0 2560 0 4947 2688
<! b 3 0 2560 0 3489 2439
!> b 3 0 2560 0 3495 2437and <! p 2 47 2505 8 17747 5163
!> p 2 46 2506 8 17743 5161
<! b 3 0 2560 0 4003 2819
!> b 3 0 2560 0 3999 2814
<! p 2 48 2503 9 17272 5148
!> p 2 48 2503 9 17271 5145
<! b 3 0 2560 0 3695 2587
!> b 3 0 2560 0 3705 2596
<! p 2 47 2512 1 17926 5131
!> p 2 47 2512 1 17929 5132
<! b 3 0 2560 0 3206 2219
!> b 3 0 2560 0 3204 2215
<! p 2 45 2511 4 17892 4939
!> p 2 46 2510 4 17906 4939
<! b 3 0 2560 0 4197 2658
!> b 3 0 2560 0 4220 2673
<! p 2 111 2442 7 18951 5259
!> p 2 112 2441 7 18939 5250
<! b 3 0 2560 0 2699 1958
!> b 3 0 2560 0 2699 1952
<! p 2 75 2474 11 16939 4795
!> p 2 75 2474 11 16949 4799
<! b 3 0 2560 0 3496 2529
!> b 3 0 2560 0 3493 2529
<! p 2 68 2484 8 17503 4963
!> p 2 68 2484 8 17502 4963
<! b 3 0 2560 0 3120 2309
!> b 3 0 2560 0 3113 2298
<! p 2 70 2480 10 18055 4899
!> p 2 70 2480 10 18068 4894
(continues)
fwiw, output files
Koepi 118,568,960 bytes
mine 118,566,912 bytes
Does this provide any clues as to what / where / why they are differant?
How do you determine which one is "correct"?
henryho_hk
20th April 2007, 02:44
Celtic Druid's 01 Apr builds are nearly 1MB. I am using Celtic Druid's March builds because the April snapshot seems to have problems in 2-pass rate control.
It appears to be difficult to judge the "correctness" as we don't even have a reference code base (which beta, alpha or even snapshots?) nor build (maybe plain MSVC 7 or old stable GCC w/o any optimization?).
Dark Shikari
20th April 2007, 03:08
If they are using exactly the same codebase, the only thing I can think of is that he's using some option like -ffast-math that doesn't abide perfectly by the ANSI C standards. Its most likely that you're using different codebases though.
plugh
20th April 2007, 04:16
The source kit is the "Xvid 1.1.2 stable release" source kit from xvid.org. The source kit includes "Generic install procedure for Win32/MSVC" instructions (from 2004), and includes MS Visual Studio workspace and project files. Assuming you have the required software, unzip it, open the workspace, select the project, and build it. Done!
I believe Koepi's build is also based upon this code base.
Like I said, the only glitch I encountered is that the canned build wants to use a "Qipo" compile switch, which MSVC noted and ignored.
To be fair, the bulk of the encode appears to be the same - perhaps 500 frames out of the 7800 were differant. But that still seems like a lot from simply using a differant compiler.
henryho_hk
20th April 2007, 06:46
Sorry for my ignorance.
Isn't "/Qipo" an ICL option? Owing to the past records of ICL, I believe your pure MSVC compile is more "correct".
plugh
20th April 2007, 07:29
Yes, from what I was able to find on the net, I believe that is an Intel C compiler option. I too thought that was odd, coming from the Xvid canned Visual Studio project files.
I have a (not-installed) copy someplace in my archives. I vaguely recall there was some kind of integration, where you could substitute it for the MS C compiler - compatible command lines etc. But the docs included in the xvid source kit don't mention it at all, just gcc and MSVC.
celtic_druid
21st April 2007, 09:45
Yeah, with ICL installed there is an option in VC6 to pick what compiler to use. /Qipo enables multi-file optimisation.
plugh
21st April 2007, 17:10
Hmmm. So perhaps I should try using ICL and see what happens.
As there doesn't appear to be a clear answer as to which is "correct", it occurred to me to ask 'which is better'? In that context, I stumbled across this MSU Video Quality Measurement Tool (http://www.compression.ru/video/quality_measure/video_measurement_tool_en.html) which appears to be tailor made for this - allowing comparison between source (avs input) and two alternative encodes (avi input).
Has anyone else used this tool? Any advice?
sysKin
22nd April 2007, 08:46
The output should be identical regardless of the compiler. Something's funny, maybe Koepi used some earlier sources?
celtic_druid
22nd April 2007, 13:52
In that case I guess also try my 1.1.2 compile since it was also compiled with ICL. See if the output matches.
plugh
22nd April 2007, 15:25
Koepi and celtic_druid builds produced identical results.
So it seems safe to conclude both used same sources, and both used ICL?
celtic_druid, did you use the 1.1.2 source kit download zip file, or cvs?
Anyone got a gcc build of 1.1.2 xvidcore.dll ?
Guess I'll dig out ICL from my archives, and see what that gives me...
EDIT: change 'identical' to 'nearly identical' - the .pass files *are* identical, the avi files differ by _one_ byte part way in.
celtic_druid
22nd April 2007, 15:40
Could have been zip/tar.bz or CVS. Can't remember.
http://ffdshow.faireal.net/mirror/XviD/gcc/xvid-1.1.2gcc.7z
Should be a bunch of gcc builds for different CPU's from recollection.
plugh
22nd April 2007, 18:28
As I'm using an 'Applebred' (Duron 1.8Ghz) cpu, I used the gcc Athlon-XP build (and I'm not overclocking).
Results:
Comparing the Koepi and gcc-xp .pass files, I get a set of differences ("set1")
Comparing gcc-xp and my-msvc .pass files, I get a set of differences ("set2")
Comparing my-msvc and Koepi .pass files, I get a set of differences ("set3")
-->in the context of this test clip<--
set3 has the smallest number of differences, set2 the largest.
working from smallest to largest, comparing
set3 and set1 - there are two frames in set3 not in set1
(set3 is NOT a proper subset of set1)
set1 and set2 - set1 IS a proper subset of set2
I'm using a differant clip than I used above; with this clip, ALL the differences are B-frames (no P-frames like above).
I also dug out and installed ICL 9.0.28 (fairly old), recompiled using it, and compared to Koepi .pass file - only three frames differant, interestingly 2 P's and 1 B, and only by one byte lengths.
plugh
22nd April 2007, 19:39
Another quick set of comparisons...
Same clip as above, same three builds (Koepi, my-msvc, gcc-xp)
This time, vhq=0 and 'vhq for b-frames' off (was vhq=3 and 'on' above)
my-msvc vs gcc-xp - .pass files were identical, and _one_ byte difference in avi files (same byte position as above when comparing Koepi and druid ICL builds, but differant values)
Koepi vs gcc-xp, and Koepi vs my-msvc - many differences, including both P and B frames
So msvc and gcc give same results, until you turn on vhq.
ICL builds give lots of differences from ths common result.
(I stated this previously, but as a reminder, these were 'full quality' first passes; NOT using the fast approximation routines.)
plugh
22nd April 2007, 23:35
More comparisons between msvc and gcc build...
They continue to produce identical results, across the entire range of vhq settings, as long as "VHQ for B-frames" is off.
Looks like there is a something in estimation_rd_based_bvop.c and/or its unique subordinates that cause msvc/gcc to differ.
These tests also lead to the conclusion that the ICL builds are BORKED.
I'm continuing to compare behaviour on other code paths - qpel, gmc, ...
sysKin
23rd April 2007, 01:56
They continue to produce identical results, across the entire range of vhq settings, as long as "VHQ for B-frames" is off.
Looks like there is a something in estimation_rd_based_bvop.c and/or its unique subordinates that cause msvc/gcc to differ.
You're on to something here ~~ perhaps you'll find the evil elusive bug that causes the output sometimes (very very rarely) depend on number of threads.
plugh
23rd April 2007, 02:52
I'm not doing multiple threads, so not sure how this helps that.
FYI - I've been using a custom profile that has 4MV off; but have tested 4MV on as well, and so far there does not seem to be dependance on that flag elsewhere - the two builds continue to give identical results with vhq-b off.
I've decided to hold off on the qpel testing; I don't use it anyway, and it further multiplies the number of tests. (Though I did do one; vhqb=off, vhq=4, 4mv=on, qpel=on, h263, yeilding a single p-frame difference between the builds.)
There seem to be three major predicates in that vhq-b module; h263 or not, inter4v or not, qpel or not. So I'll try some test cases and see what turns up...
But I'm back to my "original" problem - which build (msvc, gcc), if either, is behaving "correctly"? Perhaps this is a gcc glitch...
Are there any xvidcore.dll builds around using yet another compiler? The ICL ones are out, since they differ no matter what encoder options I select...
BTW syskin, perhaps you can answer a question. I've noticed a several constructs in that module similar to this one switch(mode) {
case MODE_DIRECT: return Data_d->iMinSAD[0];
case MODE_FORWARD: return Data_f->iMinSAD[0];
case MODE_BACKWARD: return Data_b->iMinSAD[0];
default:
case MODE_INTERPOLATE: return Data_i->iMinSAD[0];My question is - is 'case interpolate' the correct path when mode is DIRECT_NONE_MV or (in particular) DIRECT_NO4V?
plugh
23rd April 2007, 15:32
Continuing my comparisons between msvc to gcc,
I tried various relevant encoder options to probe
the "vhq for b-frames" behavioural difference.
The results were inconclusive.
So I decided to try a differant tack.
Note that I am using a Duron 1.8GHz
that has mmx, xmm, sse, 3dne, 3dne2
Using encode options vhq-b=on, vhq=1, 4mv=off
(this is _a_ case where msvc and gcc builds differ)
Using a normal 'optimized' msvc build, compare
h263,default h263,mmxonly identical
mpeg,default mpeg,mmxonly differant
Using a build with estimation_rd_based_bvop.c compiled noopt
h263,default h263,mmxonly identical
mpeg,default mpeg,mmxonly differantSo far so good. Horizontal differences, while not ideal,
*may* simply indicate an accuracy difference between the
mmx asm routines, and the default mixed, non-orthogonal,
set used on my processor.
Now if there is NO optimization sensitivity on the relevant
C code paths, then comparing the above 8 encodes *vertically*
should give me all identical comparison results. They don't!
identical identical
DIFFERANT identicalTo make this clear, whether this module is optimized or not
*should* have no effect on its results. The vertical comparisons
*should* all be 'identical'. But it appears there is an interaction
between the optimization status of this module and the default mix
of asm routines used on my processor. This is not good.
For what it's worth, the relevant asm routines are:
quant_mpeg_inter_xmm and dequant_mpeg_inter_3dne
--vs--
quant_mpeg_inter_mmx and dequant_mpeg_inter_mmx
(and perhaps fdct_mmx_skal vs fdct_xmm_skal )
These are called from within two 'large' static inline routines.
Block_CalcBits_BVOP and Block_CalcBits_BVOP_direct
These two inline routines are virtually identical (only ONE line
is differant), and they are invoked multiple times both within
and outside of loops. My gut tells me that the various compiler
optimizers are having a field day with this.
Where to go from here? Beats me - perhaps someone 'out there'
can look at those asm routines and the relevant C code and figure
out why there is an interaction with the C compiler's optimizer...
Dark Shikari
23rd April 2007, 17:03
It sounds like you're using an option like -ffast-math (GCC example) that causes deviation from the ANSI C standard.
sysKin
23rd April 2007, 17:36
It sounds like you're using an option like -ffast-math (GCC example) that causes deviation from the ANSI C standard.
It's a floating point option, it's completely irrelevant.
plugh
23rd April 2007, 22:24
The difference set in my preceding post, between the two mpeg+default cpuflags encodes (using opt or noopt on that bvop rd module) consists of a ~180 frame sequence of P and B frames, starting at a P frame. It ends at the next I frame. The rest of the 5000 frame clip is identical.
Very curious indeed - somehow opt/noopt of *this* module polluted / affected a P frame?
Ran another series of tests, expanding on the 'diff' axes
constant -> vhq-b=on, vhq=1, 4mv=off, mpeg
variable -> range of cpu flags
10 encodes
/diff\ /same\ /same\ /SAME\
full optimize mmx xmm sse 3dn 3de
| | | | |
same same same same DIFF
| | | | |
noopt bvop rd mmx xmm sse 3dn 3de
\diff/ \same/ \same/ \DIFF/
I really don't know what to make of this. Going from 3dn to 3de switches in a fairly sizable set of asm routines, including dequant_mpeg_inter_3dne. When estimation_rd_based_bvop is compiled with optimizer, I get same results as with xmm, sse, and 3dn. But when it is compiled noopt, this causes results to change. (Or perhaps result was *supposed* to change in the optimized build case, but didn't?)
Well, at least it further narrow things down...
plugh
24th April 2007, 00:44
Well, I still don't know what/why, but I can say this particular issue IS _directly_ related to asm routine dequant_mpeg_inter_3dne (in module quantize_mpeg_xmm.asm) and NOT the other 3dne asm routines...
I modified xvid.c and commented out the function pointer assignment for this routine, leaving all others alone. Rebuilt, with bvop rd still 'noopt', reran that corner case, and now output matches.
Really need someone who knows those SIMD instructions to look at that routine... Why, with the routine enabled, do we get differant output for the 'opt' and 'noopt' cases?
Dark Shikari
24th April 2007, 14:36
It's a floating point option, it's completely irrelevant.
Wait, xvid doesn't use floating point?
plugh
24th April 2007, 15:26
Wait, xvid doesn't use floating point?
I can't comment in general, but I don't see any in that module at least. I do know there are floats in plugin_2pass2, but that wouldn't impact this.
I remembered I had a VMware virtual machine with W2K and a gcc setup on it (Msys 1.0.10, MinGW 4.1.0, gcc 3.4.4). Added nasm, installed xvid 1.1.2 sources, tried doing a build - success! So now I can poke at the gcc built version and see what it reveals about that module.
FWIW, the canned xvid+gcc build procedure uses the following gcc flags:
-Wall -O2 -fstrength-reduce -finline-functions -freduce-all-givs -ffast-math -fomit-frame-pointer
(note the 'fast-math' referred to earlier)
Guess I need to read up on them...
re-EDIT: Just did a quick one shot encode comparison between gcc build with/without fast-math flag --> one B frame is slightly differant in the .pass files. However, the gcc build *with* fast-math and msvc are in agreement on that particular frame.
plugh
24th April 2007, 20:43
re: opt/noopt and asm routines
Could this be a case of a missing emms/femms someplace?
EDIT: Just tried an experiment, and it looks like the answer is "yes".
plugh
25th April 2007, 21:26
It has been an extremely tedious process, but I have tracked back to a specific chunk of code that gives differant results when compiled with msvc vs gcc.
(When I say tedious I mean it - tracking backwards through the code, identifying where a particular rd mode evaluation for a particular macroblock for a particular frame goes weird)
The chuck of code isstatic __inline uint32_t
d_mv_bits(int x, int y, const VECTOR pred, const uint32_t iFcode, const int qpel)
{
unsigned int bits;
x <<= qpel;
y <<= qpel;
x -= pred.x;
bits = (x != 0 ? iFcode:0);
x = -abs(x);
x >>= (iFcode - 1);
bits += r_mvtab[x+63];
y -= pred.y;
bits += (y != 0 ? iFcode:0);
y = -abs(y);
y >>= (iFcode - 1);
bits += r_mvtab[y+63];
return bits;
}in motion_inlines.h; r_mvtab is defined there as well.
The arguments being passed in this particular case are
x=-64 y=63 pred={x=63,y=15} iFcode=2 qpel=0
msvc produces the value 4128837
gcc produces the value 14
I manually calc it, and I get 26
The call stack is:
ModeDecision_BVOP_RD ->
SearchInterpolate_RD ->
CheckCandidateRDInt ->
the first instance in the following statementrd += BITS_MULT * (d_mv_bits(xf, yf, data->predMV, data->iFcode, data->qpel^data->qpel_precision)
+ d_mv_bits(xb, yb, data->bpredMV, data->iFcode, data->qpel^data->qpel_precision));
WTF! :confused: :( :mad: :angry: :eek:
plugh
25th April 2007, 22:24
Found another one; differant macroblock, differant rd mode
The arguments being passed
x=63 y=24 pred={x=-64,y=-20} iFcode=2 qpel=0
msvc computes 4128837 (again)
gcc computes 14 (again)
I manually calculate 26 (again)
Call stack is
ModeDecision_BVOP_RD ->
SearchBF_RD (mode is Forward) ->
CheckCandidateRDBF ->
The following linerd += BITS_MULT*(d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision)-2);
plugh
25th April 2007, 23:10
Bingo - I see it!
-127 integer divide by two is -63
-127 shift right once (sign extended) is -64
It's going out the top of the array...
So the next question is -
Is this a bug in the routine, or is "-64" an illegal/out-of-range value for a vector?
Perhaps some asm routine not rounding / range limiting correctly?
plugh
26th April 2007, 02:27
Well as an experiment, I changed three lines in motion_inlines.h
static const int r_mvtab[64] = {
to
static const int r_mvtab[65] = {12,
bits += r_mvtab[x+63];
to
bits += r_mvtab[x+64];
bits += r_mvtab[y+63];
to
bits += r_mvtab[y+64];
then created normal msvc and gcc optimized builds and did four encodes - vhq-b=on, vhq=1, 4mv=off, with both h263 and mpeg quant, with both dlls.
Compared the paired output .pass and .avi files, and they are identical now!
Not saying the above is a "fix", but it does seem to show that both compilers are generating equivalent functional representations of the source code (unlike the ICL builds). I'll probably run some more comparison series (range of VHQ, range of cpu-flags), but I have much greater confidence that my builds are 'right' now.
I hope someone knowledgable will chime in and indicate if "-64" is a valid value for a vector component - if it is, then the above *is* a fix. If not, it's just a workaround for some badly behaved code elsewhere (which both msvc and gcc compilers are building as directed :rolleyes: ) Might be interesting to see if this change improves psnr/ssim/xyzzy... :)
The other weirdness with the opt vs noopt msvc builds and that one asm routine - I'm not sure what to think about that one. As an experiment, I added a 'femms' instruction to the asm file just before the return, and it magically caused the noopt build to produce the same output as the opt build - not the other way around. :confused: Again, I hope someone more knowledgable will look at that oddity...
Manao
26th April 2007, 06:10
A motion vector goes from -2^x to 2^x - 1/2 ( or 1/4 for QPel ), so yes, -64 is valid ( in your case, -64 is -16 integer pixels, and 63 is 15.75 integer pel ).
sysKin
26th April 2007, 10:03
Whoa plugh what a great work.
Yes -64 is valid. So we were nicely reading r_mvtab[-1]? Great, I wonder why memory access analysis tools didn't pick it up :)
I suppose I should stick this d_mv_bits() after motion vector writing code and assert that calculated length is the actual bitstream length. This will make us 100% sure nothing else is wrong.
Although, then again, I did have such assertion for a whole macroblock (part of VHQ debugging). I suppose vectors of -64 were never chosen (as they appeared to be horribly costly, 44 kilobits!) and therefore assertion was never hit.
plugh
26th April 2007, 13:44
So that three line change *can* be considered a "fix" for 1.1.2?
Given I'm only working with "HD" encodes (and with 4mv off), perhaps that magnitude of vector is somewhat more likely? ie MB displacement across X% of the image literally crosses more pixels? (Don't know what I'm talking about, but it sounds good anyway ;) )
BTW, there was one other thing in the huge volume of debug print data I collected that struck me - I'll pass it on, for whatever it is worth.
In ModeDecisionBVOP_RD, right after the "evaluate cost of all modes" loop, the values for d_rd, f_rd, b_rd, i_rd were frequently the same (with my short test clip). The code is evaluating the modes in increasing SAD order, but in this case should it simply choose the 'first' mode at that cost?
EDIT: Duh - stupid question; you want the one with the lowest SAD. never mind...
Anyway, it happens enough (multiple modes yeilding same rd) in my data that it caught my eye, so I thought I'd mention it. Seemed odd, given radically differant code paths.
Examples: - Frame 182, the 4 SADs, evaluation order stuff, x/y of MB, the four RD costs, the chosen cost/mode
182 ds=464 bs=301 fs=464 is=238 bst=238 order=1 2 0 3 num=4 I0 B1 D2 F3 x=41 y=0 d=770 f=786 b=770 i=770 rd=770 mod=1
182 ds=324 bs=306 fs=340 is=216 bst=216 order=1 2 0 3 num=4 I0 B1 D2 F3 x=22 y=1 d=1179 f=1195 b=1179 i=1179 rd=1179 mod=1
plugh
27th April 2007, 08:31
Out of curiosity, I also did a build using ICL 9.0.28 with the above "fix", and compared it to the msvc/gcc builds.
The difference set is now much smaller, however there are still differences. I've poked at it some, and made the following observations.
1) Ever so often, the VOP header is a single bit longer than 'usual'. This extra bit is sometimes enough to cause the byte-padded frame to be a single byte longer. The msvc and ICL builds do not do this 'in sync' with each other. Thus, a comparison of the .pass files for ICL vs msvc shows occasional one byte frame length differences. No such difference is observed comparing msvc vs gcc .pass files.
The source of this difference in behaviour is the following routine in encoder.csimplify_time(int *inc, int *base)
{
/* common factor */
const int s = gcd(*inc, *base);
*inc /= s;
*base /= s;
if (*base > 65535 || *inc > 65535) {
int *biggest;
int *other;
float div;
if (*base > *inc) {
biggest = base;
other = inc;
} else {
biggest = inc;
other = base;
}
div = ((float)*biggest)/((float)65535);
*biggest = (unsigned int)(((float)*biggest)/div);
*other = (unsigned int)(((float)*other)/div);
}
}
In my case avisynth was feeding an 'inc' of 41708 and 'base' of 1,000,000. The above code, in attempting to normalize the base to 65535, actually returns 65534 with the ICL build. :(
2) If I encode a very short sequence of frames (so that I don't encounter that extra bit/byte 'time' thing above), then binary compare the avi files, I consistently show a single byte difference per frame. In my test case, the msvc build will have an 'FF' where the ICL build has an 'FB'. I don't have any tool to parse the avi and tell me where this byte is in the frame (though I would guess it's at the end?)
Again, the msvc and gcc builds show no such difference. I'm suspicious of the "bitstream" code in this case, but will leave that as 'an exercise' for someone else... :rolleyes:
plugh
27th April 2007, 15:56
When I did my initial "fixed" msvc/gcc/icl compare above I collected one other datum, which yielded a quite surprising comparative result:
time (min:sec) to complete test-clip encode
msvc gcc icl
h263 quant 16:11 16:30 16:39
mpeg quant 17:35 17:52 18:22
dll size 580KB 728KB 808KB
I did NOT expect this.
The only hypothesis I can come up with is that the more compact dll works better with my cache-challenged Duron processor. Guess which one I'll be using for my future encodes ;)
If anyone wants to experiment, attached is msvc build of v1.1.2 xvidcore with the above arraysize "fix".
EDIT: withdrawn, based upon syskin's post below. Updated build here (http://forum.doom9.org/showthread.php?p=995725#post995725)
foxyshadis
28th April 2007, 07:01
If it helps, avisynth had its own problems with fps and ended up with this function to fix things up:
// This function uses continued fractions to find the best rational
// approximation that satisfies (denom <= limit). The algorithm
// is from Wikipedia, Continued Fractions.
//
static void reduce_frac(unsigned &num, unsigned &den, unsigned limit)
{
unsigned n0 = 0, n1 = 1, n2, nx = num; // numerators
unsigned d0 = 1, d1 = 0, d2, dx = den; // denominators
unsigned a2, ax, amin; // integer parts of quotients
unsigned f1, f2; // fractional parts of quotients
int i = 0; // number of loop iterations
while (1) { // calculate convergents
a2 = nx / dx;
f2 = nx % dx;
n2 = n0 + n1 * a2;
d2 = d0 + d1 * a2;
if (f2 == 0) break;
if ((i++) && (d2 >= limit)) break;
n0 = n1; n1 = n2;
d0 = d1; d1 = d2;
nx = dx; dx = f1 = f2;
}
if (d2 <= limit)
{
num = n2; den = d2; // use last convergent
}
else { // (d2 > limit)
// d2 = d0 + d1 * ax
// d1 * ax = d2 - d1
ax = (limit - d0) / d1; // set d2 = limit and solve for a2
if ((a2 % 2 == 0) && (d0 * f1 > f2 * d1))
amin = a2 / 2; // passed 1/2 a_k admissibility test
else
amin = a2 / 2 + 1;
if (ax < amin) {
// use previous convergent
num = n1;
den = d1;
}
else {
// calculate best semiconvergent
num = n0 + n1 * ax;
den = d0 + d1 * ax;
}
}
}
Hopefully Intel would be kinder to this one, as well as giving smaller fractions.
celtic_druid
28th April 2007, 10:17
Maybe -Os or -O2 -fno-reorder-blocks -fno-reorder-functions would be faster for Duron's? That along with -march=athlon-xp
plugh
28th April 2007, 17:27
I just used the canned build options from the source kit, as my focus was getting the builds to produce identical output.
I may experiment in that area some, but it would mean re-running encoder output comparisons (a time consuming process) to insure such tweaks didn't change the results - like that msvc opt/noopt oddity I discuss above...
sysKin
28th April 2007, 17:37
OK I committed the d_mv_bits out-of-bouds memory access bustage.
Unfortunately the fix is not correct. For some negative vectors which land in the range mv_table[64-34]..[64-64], the correct value seems to be 11 not 12.
I added an assertion that fails when incorrectly-estimated vector is coded.
I am not sure if the logic is incorrect in one place, or maybe the entire mv_bits can't be calculated in such "smart", branchless way. Following the code from CodeVector is surely correct but unfortunately measurably slower.
We should just use a LUT.
Anyway, overestimating cost by one in those rare cases (I need to encode over 200 frames to hit the assertion) should have absolutely no effect on quality.
plugh
28th April 2007, 18:04
The "12" I used in the extra cell was just a guess, based upon the perceived pattern in the array. My goal was to eliminate this as a cause of differing output, to see if there were other causes still present. I'm glad to have someone knowledgable build upon my discovery.
EDIT: I reviewed the changes syskin committed, and now better understand his post.
It isn't simply that the "12" I used should be "11", but that the debug check he added to mbcoding.c reveals that the "12" in some of the _existing_ cells is slightly too high an estimate for _some_ vectors... That perhaps the 'slick/fast' code in d_mv_bits isn't as accurate as it could be (I'll leave that one to the experts), but that the error should have little if any effect.
In any event, my "fix" (with the corrected value), is OK for the existing implimentation, as grabbing random garbage from outside the array definitely isn't right.
Many thanks, syskin...
(Updated 1.1.2 msvc build attached)
sysKin
29th April 2007, 08:18
In any event, my "fix" (with the corrected value), is OK for the existing implimentation, as grabbing random garbage from outside the array definitely isn't right.
Yes exactly. Think what would happen if the value there was negative O_O Such vector would be always chosen, regardless how bad it would be.
Many thanks, syskin...
Nono, thank YOU!
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.