View Full Version : VagueDenoise optimization
sh0dan
7th July 2003, 14:43
Did some profiling on the VagueDenoiser. Some overall numbers:
percentage of total CPU usage:
37% void Wavelet::invert_step(float *, float *, int, int)
36% void Wavelet::transform_step(float *, float *, int, int)
8% void Wavelet::invert2d(float *, float *, int, int, int, int)
8% void Wavelet::transform2d(float *, float *, int, int, int, int)
= 89% total CPU time.
Conversion char -> float -> char takes about 3% of total CPU.
So the transforms are the only ones that really need to be optimized.
In the _step functions only the two loops take up any considerable time.
In the transform/invert functions the copy functions take up all the used time there.
Lefungus
7th July 2003, 15:27
Thanks for the informations !
I'm "cleaning"/"removing" unused code.
I've made experiments with floats everywhere. It's still lossless with threshold=0, so i guess it's ok. So i've replaced everything by floats.
BTW, the plugin has always been compiled with intel compiler, however the options may not be correct. Here is the commandline:
/c /GL /Zi /nologo /W3 /O3 /Og /Ob2 /Oi /Ot /Oy /G6 /QaxW /QxM /D
"WIN32" /D "_WINDOWS" /D "NDEBUG" /D "_USRDLL" /D "_WINDLL" /D "_MBCS"
/GF /FD /EHsc /MD /GS /Gy /Zc:wchar_t /Fo"Release/
/Fd"Release/vc70.pdb" /Gd /TP
sh0dan
7th July 2003, 15:50
ok :)
Unused code shouldn't matter. Unfortunately I don't have the Intel compiler - it should however have quite a large impact on float code.
With MSVC and AMD TBird i get a considerable speedup (~30%) when using these inner loops:
for (i = 0; i < lowSize; i++) {
Real tval =0.0;
int idx = npad + 2*i + analysisLow->firstIndex;
for (j = 0; j < analysisLow->size; j++) {
tval += input[idx + j] * analysisLow->coeff[j];
}
output [npad+i] = tval;
}
for (i = lowSize; i < size; i++) {
Real tval = 0.0;
int idx = npad + 2*(i-lowSize) + analysisHigh->firstIndex;
for (j = 0; j < analysisHigh->size; j++) {
tval += input[ idx + j] * analysisHigh->coeff[j];
}
output[npad+i] = tval;
}
- idx calculated outside the innermost loop. It could even be moved completely out of the loop, using idx+=2. This can also be done for the invert_step function.
- Using a temporary value allows the value to remain in a register until the innermost loop is completed.
Edit: Ok - MSVC seems like the stupidest compiler around. Using this in invert also speeds up very nicely:
int l_start = -lastIndex/2;
int l_end = (size-1-firstIndex)/2;
for (i = l_start; i <= l_end; i++) {
int idx = npad + 2*i + firstIndex;
for (j = 0; j < synthesisLow->size; j++) {
output[idx + j] += temp[npad+i] * synthesisLow->coeff[j];
}
}
Note the "l_start" and "l_end". God this compiler is stupid. ;)
Edit 2: Strange - I cannot seem to get AviSynth to load the 0.2 binary plugin - is there any special requirements (like SSE)?
Kronos is just a godsend for optimization :)
Lefungus
7th July 2003, 16:32
Implemented the first trick, i get 5 fps, instead of 3 on a 720*550 movie :)
And that's with intel compiler (it seems he's stupid too)
And now, i see one way to improve things
on 0.2, SSE is required, but this will be removed soon, just an option of icl.exe. SSE isn't required yet.
Bidoche
7th July 2003, 17:08
I don't get the point with l_start and l_end, but I agree with you :
MSVC is definitely stupid...
By the way, you can try reversing the j loops, like this :for(int j = analysisLow->size; j-- > 0; ) {
//same as before
}It may be slightly faster
Lefungus
7th July 2003, 17:39
Shodan, with 0.21, you should be able to use the filter.
BTW what utilities are you using to do profiling ?
If you want to get really fancy you might want to check here (http://www.dacya.ucm.es/atc/es/hpc/jpeg2000/jpeg2000.htm). They give a pretty exhaustive list of possible optimizations (the most recent paper glosses over the way loop-tiling/aggregation/pipelining works, the other papers do a better job at explaining it). They also mention they would put up a hand optimized DWT using their techniques on their web page, but I dont see it :( (The site is a mess though, so I might have missed something.)
In addition if you are at a uni with a good library ... this book (http://www.wkap.nl/prod/b/0-7923-7519-X) comes with source code to MMX versions of the transforms used in JPEG2000, and a license to use it in binary distributed free software.
Kurosu
7th July 2003, 19:51
Why not make (I haven't tested) a working copy of the pointers, offset (see "int idx = npad + 2*(i-lowSize) + analysisHigh->firstIndex") them and directly update the pointers (by decrementing or incrementing)? It'll become unreadable, however.
@Sh0dan
How do you plan to account for the undefined number of sample and coefficients (up to 10, and that's the troublesome part) in the most generic loop (SSE float code)? I think it would require at least a a rewritting of the inner loop for each length... I guess a heavy use of macros and else, but a nightmare to code.
Lefungus
7th July 2003, 20:00
I've done this for the loops, as counseled by Shodan and Bidoche
lindex= -lastIndex/2;
findex= (size-1-firstIndex)/2;
idx=npad+firstIndex+2*lindex-2;
for (i = lindex; i <= findex; i++) {
idx+=2;
for (j = synthesisHigh->size; j-- >0;) {
output[idx + j] +=
temp[npad+i] * synthesisHigh->coeff[j];
}
}
But maybe it'll be faster to use an more straight-forward algorithm, that will be easier to optimize.
Thanks for the links Mfa, there is indeed some work already done on this subject.
Kurosu
7th July 2003, 20:01
@MfA
I sense a strong commercial move... Inside of this report (http://www.dacya.ucm.es/manuel/jpeg2000/papers/ipdps03_submitted.pdf), they mention an url, http://www.dacya.ucm.es/atc/jpg2000, which is no longer active. But I think they've chosen very particular wavelets, more suited for JPEG-2000 (see III.A.)
[edit]
@Lefungus
When you stated 20fps in one of your post, what was it? I don't know if Intel compiler is able to generate SSE code automatically to produce such result, but that would really be impressive
When I was talking of working on temp pointers, I meant something like:
[code]
temp = ... + someoffset
outtmp = ... +anotheroffset
loop1
loop2
...
*(outtmp++) += *(intmp++) * *(synthesisHigh->coeff++)
loop2end
loop1end
(very schematic)
But that won't work, as we're working on floats.
sh0dan
7th July 2003, 21:17
BTW what utilities are you using to do profiling ?
AMD CodeAnalyst - it's free and works great - I only wished they had their old versions up - they seem to work better than the current beta.
It's able to do generic profiling on a range of programs measuring the time each funtions and line takes. Furthermore it's able to do advanced pipeline analysis to help assembler optimization.
You should try timing your filter with and without SSE enabled to see if it actually is speeding up processing. Try Kronos or AVSTimer (if you can find it ;) )
@Kuroso:
I'm experimenting with a SoftWire based approach, but since it's my first shot at 3DNOW/SSE it takes a while. I'm not even sure there is anything to be gained - the only major advantage is an unrolled inner loop (based on the size of the transform). It would take some more work to actually get huge advantages (from pairing, etc).
Right now I'm just trying to figure out what the loops actually do to be able to optimize it.
Regarding pointer work - sometimes it's actually faster to use arrays, since the compiler is able to see what is actually going on, and take advantage of it.
Bidoche
7th July 2003, 21:37
@Kurosu
But that won't work, as we're working on floats.
Pointers arithmetics always work, being BYTE *, float * or even Whatever * doesn't enter into account.
Kurosu
7th July 2003, 21:46
@Sh0dan
Regarding SSE code, I tried to adapt the Symlet8 used in VagueDenoiser <0.2, as it was the best and one with just what was best for processing with SSE registers. I never finished it, (beside the complete rip of env->Bitblt was rather useless, as you could just change pointer and make the calling function aware of this.
Here (http://kurosu.inforezo.org/avs/Symlet.cpp) is what I tried to do, without much success, on VD0.11. I think another little benefit (that I used here) would be to allocate (eg in the Wavelet class constructor) once and for all the buffers in which the operations are done.
Lefungus
7th July 2003, 21:53
Originally posted by Kurosu
[edit]
@Lefungus
When you stated 20fps in one of your post, what was it? I don't know if Intel compiler is able to generate SSE code automatically to produce such result, but that would really be impressive
Well, i was too much enthousiast :), when properly checked it doesn't go above 15fps and the filter was after the resizing.
For versions <0.2, i don't really know why, but many artifacts were seen even with a quite low threshold. That's why i gave up with these transforms and have used another library.
Something was wrong, but i don't know why. Maybe because it was 1D transform and not 2d transform.
[edited] typos
Kurosu
7th July 2003, 21:57
Originally posted by Bidoche
@Kurosu
Pointers arithmetics always work, being BYTE *, float * or even Whatever * doesn't enter into account.
Yes... :rolleyes:
Too much assembly programming lately...
sh0dan
8th July 2003, 10:38
@Lefungus: Can I assume that:
*) analysisLow / analysisHigh / synthesisLow / synthesisHigh are constant for each Wavelet class instance, and parameters within these never changes, as long as the Wavelet class exists?
*) Can I assume anything about filter sizes? Any relation between sizes of analysisLow / analysisHigh / synthesisLow / synthesisHigh?
Lefungus
8th July 2003, 13:28
Well, i've just used this library without much understanding about how it worked internally. That's what i'm trying to do now. So i have no idea about your questions yet. May Kurosu may help there ?
ok, back to deciphering this.
Lefungus
8th July 2003, 15:14
Originally posted by sh0dan
@Lefungus: Can I assume that:
*) analysisLow / analysisHigh / synthesisLow / synthesisHigh are constant for each Wavelet class instance, and parameters within these never changes, as long as the Wavelet class exists?
*) Can I assume anything about filter sizes? Any relation between sizes of analysisLow / analysisHigh / synthesisLow / synthesisHigh?
Ok, more informations:
The filterset is defined one time for all at its creation. So analysisLow/analysisHigh/synthesisLow/synthesisHigh won't change ever after.
About filters sizes, i'll separate FilterSets in two categories:
- Orthogonal filterSets ( Haar, Daub4/6/8, Adelson):
The four filters are the same size. And SynthesisLow coeff. are strictly equal to AnalysisLow. Same for SynthesisHigh and analysisHigh
- Biorthogonal filterSets (all others filtersets):
AnalysisLow and SynthesisHigh have the same size. Same for SynthesisHigh and AnalysisHigh
It seems that orthogonal wavelets will be more "optimizable" than biorthogonal wavelets. Unfortunately, my results so far show that the later gives better results. But maybe visual results are simply related to filters sizes, the bigger, the better. And the bigger one is biorthogonal (Brislawn2). Any wavelet expert there ? :)
As Kurosu said before, symmetry helps in image processing (asymetric filters cause asymetric artifacts). Orthogonality and symmetry dont go together (except for the Haar wavelet).
That the inner loop between analysis and synthesis is of different size only requires a few more lines of code, but it doesnt mean there is less room for optimization AFAICS.
I had a cute idea for a wavelet transform BTW (although mostly for lossless compression). I wonder how good a transform you would get if for say each 16x16 block of pixels you calculated optimal linear phase predict/update filters (assuming lifting).
Lefungus
8th July 2003, 18:56
I might have been confused a little :)
All wavelets implemented are symetric except Harr and variations of Daubechies. Daubechies give indeed awful results.
Anyway, the papers you mentionned before are very interesting. It seems they have huge improvements when "tiling" the processing in blocks, then in each block process vertical filtering by rows instead of columns.
Now the vertical filtering is done on the whole image by columns, then by rows for the horizontal filtering.
After that, they use vectorisation, but i'm not sure i really understand this part.
Lefungus : dunno if you noticed, but the j2000.org code uses 64 bit integers for it's fixed point calculation ... that cant be healthy for speed.
Also I think the coefficients have an additional scaling factor in this implementation, something to do with those dwt_norms arrays, you might want to consider comparing results of the transform to another Daubechies 9/7 transform (BTW all the results are in 19.13 fixed point format I think).
Lefungus
9th July 2003, 10:20
Mfa pointed me on j2000 reference code.
http://j2000.org
It happens it's nearly 15 fps on a 692x416 video (not resized) and this with 64 bits integers. [edited] With Daubechies 5/3 filter.
As it's still unoptimized C code, i'll work on it as it shows much more promises. Unlike the previous code, it uses a fairly 'recent' development in wavelets that are lifting tranforms. It's much more understandable and clear.
I've learned much about it there:
http://perso.wanadoo.fr/polyvalens/clemens/lifting/lifting.html
My first implementation isn't usable yet, some kind of artifacts. But i hope i'll manage to fix it.
In the end, it should be able to use almost all filters that are currently used in 0.2
sh0dan
9th July 2003, 12:06
In general I'd _think_ there would be more "room for improvement" in float transforms, as no current hardware supports int64 natively. I don't know about SSE2, but MMX/SSE has no way of doing int64 calculations.
This might however be a beast on the new Athlon64/Opteron, when they become widely available.
I assume I'm to look for the current code on libj2k until you get a version out?
[Looking at it...]
ok - seems like it uses int most of the way through!???
From the looks of it, it uses a 13 fraction part - or maybe that's only the multipler.
You might want to try to add "__inline" to the the fix_mul (fix.c) function.
__inline int fix_mul(int a, int b) {
return (int)((int64)a*(int64)b>>13);
}
I don't know abot the Intel compiler, but MSVC doesn't inline, unless you tell it to inline "Any suitable". It seems to be used a lot, so making sure it's inlined will make it much faster.
Lefungus
9th July 2003, 12:22
Its beginning to get hard, but if i can it will use float transforms
trbarry
9th July 2003, 15:02
In general I'd _think_ there would be more "room for improvement" in float transforms, as no current hardware supports int64 natively. I don't know about SSE2, but MMX/SSE has no way of doing int64 calculations.
I don't know what level they came in but what about paddq, psubq, etc. You can at least load, store, shift, add, subtract, and, or, etc. even if the VS6 compiler still does most of these by function call.
But I came into this thread late so maybe I'm missing something here.
- Tom
sh0dan
9th July 2003, 16:15
Originally posted by trbarry
I don't know what level they came in but what about paddq, psubq, etc. You can at least load, store, shift, add, subtract, and, or, etc. even if the VS6 compiler still does most of these by function call.
paddq, psubq are not a part of MMX/SSE, AFAIK - are they SSE2 commands?
trbarry
9th July 2003, 21:30
I've never had reason to use paddq, etc. I'm guessing they are only for SSE2 since the only Intel reference manuals mentioning them also mention the xmm registers. But the way Intel documents these it is hard to tell. Sorry.
- Tom
Lefungus
10th July 2003, 16:33
Ok, i've released 0.22 under GPL.
Not much changes.
In order to improve algorithms speed, i need to learn a lot more about wavelets. So i'll put it to rest for a while. If anyone is interested, one thing could be to implement lifting transforms instead of those used now. there are some libraries on the net that does this but i don't really understand them yet.
@Shodan: Sorry, i won't use any j2000 code soon :/. I hope you haven't taken too much time on it. Anyway, it'll be still great if you manage to squeeze some speed from current version. Wavelet.cpp ins unchanged from 0.21
vass-iliskus
13th July 2003, 18:44
Originally posted by Lefungus
I've done this for the loops, as counseled by Shodan and Bidoche
lindex= -lastIndex/2;
findex= (size-1-firstIndex)/2;
idx=npad+firstIndex+2*lindex-2;
for (i = lindex; i <= findex; i++) {
idx+=2;
for (j = synthesisHigh->size; j-- >0;) {
output[idx + j] +=
temp[npad+i] * synthesisHigh->coeff[j];
}
}
Hi,
Loading temp[npad+i] into a variable (FP register, actually) could shave another 10% cycles off the loop. At least my MSVC6 does not perform loop invariant motion on it. The code could look like this:
for (i = lindex; i <= findex; i++) {
idx+=2;
float tmp = temp[npad+i];
for (j = synthesisHigh->size; j-- >0;) {
output[idx + j] +=
tmp * synthesisHigh->coeff[j];
}
}
sh0dan
15th July 2003, 13:30
@vass-iliskus: Yes - seems like we missed that one. I must say I had more faith in the compilers until this. I thought compilers were able to simple "move-constants out of loops" optimizations - but it seems like this isn't always the case. :(
Lefungus
18th July 2003, 20:04
Critical loops looks like that now
idx=4;
int idx2=10+lowSize;
for (i=0;i<lowSize;i++) {
idx+=2;
output[10+i]=input[idx]*analysisLow[0]+input[idx+1]*analysisLow[1]+input[idx+2]*analysisLow[2]+input[idx+3]*analysisLow[3]+input[idx+4]*analysisLow[4]+input[idx+5]*analysisLow[5]+input[idx+6]*analysisLow[6]+input[idx+7]*analysisLow[7]+input[idx+8]*analysisLow[8]+input[idx+9]*analysisLow[9];
output[idx2+i]=input[idx]*analysisHigh[0]+input[idx+1]*analysisHigh[1]+input[idx+2]*analysisHigh[2]+input[idx+3]*analysisHigh[3]+input[idx+4]*analysisHigh[4]+input[idx+5]*analysisHigh[5]+input[idx+6]*analysisHigh[6]+input[idx+7]*analysisHigh[7]+input[idx+8]*analysisHigh[8]+input[idx+9]*analysisHigh[9];
}
It should be easier to asm them i think.
All my attempts to "tile" the processing have failed yet, but i don't give up !
Kurosu
18th July 2003, 23:04
I'm writing a 3DNow! version of 0.24, the only thing I can test, as I don't have a float-SSE capable machine. Speed improvement is almost unnoticeable, but maybe that's memory bandwidth that is limiting. Debugging is still needed, as I got blocky results (some iterations improperly ended, I guess).
Anyway, I have another minor improvement (haven't tested how much, but it can't hurt):
declare the FIR arrays (analysis*, synthesis*) as static const float...
Kurosu
19th July 2003, 12:58
Other suggestions:
- the absolute value for float is fabsf, not fabs (for double): one less warning
- the static const float arrays should hold values like -0.0.....f: that removes a lot of warnings
- in VagueDenoiser::GetFrame, the plane copies for U and V should be done with env->BitBlt:
if(chroma){
//Filter U Plane
srcp = src->GetReadPtr(PLANAR_U);
dstp = dst->GetWritePtr(PLANAR_U);
filterBlockYV12(heightU,widthU,srcp,dstp,src_pitchU,dst_pitchU,size_UV);
//Filter V Plane
srcp = src->GetReadPtr(PLANAR_V);
dstp = dst->GetWritePtr(PLANAR_V);
filterBlockYV12(heightU,widthU,srcp,dstp,src_pitchU,dst_pitchU,size_UV);
} else {
//Copy U Plane to Destination
env->BitBlt(dst->GetWritePtr(PLANAR_U), dst_pitchU, src->GetReadPtr(PLANAR_U),
src_pitchU, widthU, heightU);
//Copy V Plane to Destination
env->BitBlt(dst->GetWritePtr(PLANAR_V), dst_pitchU, src->GetReadPtr(PLANAR_V),
src_pitchU, widthU, heightU);
}
This was a quick change, faster than the one that would consist in using some code from env->BitBlt to modify the copy function (with in mind the fact that a float is 4bytes and a char 1)
Lefungus
19th July 2003, 13:29
Hey many thanks Kurosu !
i'll add this (even if those warnings only appears with microsoft compiler :) )
Kurosu
19th July 2003, 15:15
Ah, well, I'm disappointed with my first 3DNow! code... I don't know if the float format used by 3DNow! is the same than the one embodied by "float" type, but aside of this, it performs only marginally faster (129ms per frame on my Duron for the full 3DNow! version against 149ms for the C only version) and is heavily bugged...
If Sh0dan is interested in looking at the code, as he probably has an Athlon, get the project files here (http://kurosu.inforezo.org/avs/VagueDenoiser.zip). Despite every asm line being commented and explained by C-like code, I won't mind if nobody looks at it (as for my previous SSE2 code).
[EDIT]
All that means 3DNow! is maybe not the best way to do it.
[EDIT2]
Removed an useless proposal
Lefungus
20th July 2003, 00:35
I've done a few changes in latest version 0.243. In those loops, all idx/idx2 has been removed. I only use "i", but with maybe-clever ways. At least i have no speed loss.
for(i=8;i<lowSize+12;i++) {
output[2*i-14]+=temp[i]*synthesisLow[0];
output[2*i-13]+=temp[i]*synthesisLow[1];
output[2*i-12]+=temp[i]*synthesisLow[2];
output[2*i-11]+=temp[i]*synthesisLow[3];
output[2*i-10]+=temp[i]*synthesisLow[4];
output[2*i-9] +=temp[i]*synthesisLow[4];
output[2*i-8] +=temp[i]*synthesisLow[3];
output[2*i-7] +=temp[i]*synthesisLow[2];
output[2*i-6] +=temp[i]*synthesisLow[1];
output[2*i-5] +=temp[i]*synthesisLow[0];
}
It's interesting to note that some coefficients are redundant. In the code above, i don't use the 10 coefficients but only 5. But it doesn't change at all the speed.
Kurosu
21st July 2003, 00:27
It is symmetrical in this regard, but considering you have the same number of multiplies, it shouldn't gain anything.
On another end, I've completely ported this to 3DNow! (my first attempt at it).
What's done:
- float->char and char->float converions
- hard thresholding (soft is harder, I did'nt want to spend more time on something unlikely to improve anything)
- transform2d and invert2d, which are the most costly.
hard thresholding is trying to use prefetching, but yields no improvement. Its use in transform2d/invert2d only slow down things. Use of iSSE (3DNow!2 ?) function movtnq slows it even more, so I guess I'm really misusing them. Therefore, any advice on this is welcome.
To build with 3DNow!, set line in wavelet.h to:
#define USE_3DNOW 1 //0 to disable it
On a Duron 700, time per frame (640x480) went from 143ms to 119ms, ie a 17% win, which is not impressive. I guess the main speed improvements can be done by:
- fix any stall due to my somewhat total lack of awareness of latencies
- fix that prefetch/prefetchw issue
- unroll loops in transform2d/invert2d (for now 40bytes/10 coefficients per loop, doing 320 would allow 5 prefetch to be put perfectly) once the above issue is fixed
- Use softwire for even more adapter code generation (Sh0dan? :)
There are also some copy functions done at the end of wavelet.cpp, which would benefit a bit from prefetching, but they aren't costly at all...
Ah, btw, to make your life easier and not look in the Users' thread, here is the stuff (http://kurosu.inforezo.org/avs/VagueDenoiser.zip)
Lefungus
28th July 2003, 17:48
My attempts to "tile" processing have completely failed. It works, but it's slower. i've played a little with vectorization, it improves things a little. I won't be able to do much more now. At least it's useable for me now.
sh0dan
28th July 2003, 18:53
@Kurosu: I looked at the code - and I couldn't see any ways of making it faster. It has nice pairing, and seems fine.
I've just got my home machine up again, so I'll see if I can do some profiling.
Regarding prefetching - it is only faster when you do not access memory linearly. Otherwise it is just unnecesary overhead.
Old Durons and Athlons dont have hardware prefetch.
Kurosu
28th July 2003, 19:21
Originally posted by MfA
Old Durons and Athlons dont have hardware prefetch.
What do you mean? Is it in reply to Sh0dan, stating that it does have a use on those processors where the prefetch isn't present (and would have to be manually triggered with prefetch or prefetchw) ?
prefetch and prefetchw (not to be confused with prefetchnt*) are there since 3DNow! 1 AFAIK.
@Sh0dan
Then should I do as in Bitblt asm functions, read backwards and if possible, aligned data? And you surprise me about pairing, because the only rule I apply is not to use immediately a register used in the previous instruction.
[EDIT]
Good thing is now that I have a float SSE-capable CPU, but it seems rather bothersome on some parts.
sh0dan
28th July 2003, 21:34
@Mfa: Do you have any further information?
@Kurosu: AMD claims that the fastest way to copy memory is:
*) Fill half the cache with data to be read.
1. Read every 64th byte (one cacheline) backwards.
2. Do not use software prefetch.
*) Write using write combiner (movntq). Must be linear _forward_ writes.
This is ONLY true when doing straight copies. If you process the data, do NOT use the write combiner, as it makes delayed (cached) writes impossible.
Richard Berg
29th July 2003, 00:08
I should note that last summer we found that this technique is very slow on Intel processors.
Kurosu
29th July 2003, 00:28
Renamed compilers, and it makes even more sense, now
I don't think it's worth to compile myself the 0.25 version, as the conclusion will be: yes the compilation is optimized for my system.
I've tested the different builds against my Barton 2800+ (512KB cache, DDR333), which behaves considerably differently from my old Duron 700... Here are the figures for a 640x480 video, using 1000 frames and letting Kronos do the measures:
- LeFungus' 0.25 VC7(=.NET) compile: 27.7ms +/- 3.1ms
- LeFungus' 0.25 ICL7.1 compile: 27.3ms +/- 2.6ms
- My VC6 compile: 22.3ms +/- 2.1ms
- My VC6 compile, using 3DNow!: 16.3ms +/- 1.3ms
The conclusions I draw:
- Finally, my code isn't that bad :)
Rather, a limitation was diminished when upgrading the system (I would think memory bandwidth due to dual-DDR, cache and overall better management system)
- As LeFungus thought his ICL version was faster than the VC7 one, and that both are slower on my system, either his modifications slowed down things, or our compiler particularly fits the compilation to the CPU (which is not at all surprising). Id est, ICL7.1 has (even) more optimization for P4 (d'oh).
- To use LeFungus' builds, you absolutely need the typical msvcr70.dll (can't avoid it, it's hard-written into the dll)
Execution times are rather impressive now (I can't believe I had like a 7x speed-up compared to my old system!). Who needs SSE optimization anyway? :)
With hardware prefetch I simply meant that the hardware recognises linear and strided-linear accesses and does its own prefetch ... older processors dont do this.
Lefungus
29th July 2003, 16:30
Originally posted by Kurosu
- LeFungus' 0.25 VC6 compile: 27.7ms +/- 3.1ms
- LeFungus' 0.25 VC7(=.NET) compile: 27.3ms +/- 2.6ms
- My VC6 compile: 22.3ms +/- 2.1ms
- My VC6 compile, using 3DNow!: 16.3ms +/- 1.3ms
- To use LeFungus' builds, you absolutely need the typical msvcr70.dll (can't avoid it, it's hard-written into the dll)
Actually, it is:
- LeFungus' 0.25 VC7 compile: 27.7ms +/- 3.1ms
- LeFungus' 0.25 ICL 7.1 compile: 27.3ms +/- 2.6ms
So it may explain why i have more speed with the icl compiled dll as i use a pentium 4. On my comp, the icl compiled dll is 4-5 ms faster ( 16 vs 11 ms for a 640x256 video).
About the msvcr70.dll issue, i think i know how to prevent it now. If anyone has trouble with it, i could provide updated dlls.
ominte
5th August 2003, 08:35
@ Kurosu,
Could you possibly provide a link to your VC6 compile using 3DNow? Thanks in advance:)
Kurosu
5th August 2003, 08:57
@Ominte
With a very little search, you would have found:
- the previous page (http://forum.doom9.org/showthread.php?s=&threadid=57084&perpage=20&pagenumber=2) in this thread.
- the official VagueDenoiser thread (http://forum.doom9.org/showthread.php?s=&threadid=56871&perpage=20&pagenumber=3)
(what? I crossposted? :D )
I could make the links clearer, but hey, do your part of the job by reading :sly:
ominte
6th August 2003, 06:26
My apologies Kurosu and Lefungus for wasting your time :rolleyes:
Kurosu
6th August 2003, 07:48
Originally posted by ominte
My apologies Kurosu and Lefungus for wasting your time :rolleyes:
No time was wasted, but sometimes it feels like people don't even do the simplest things they should do in order to work out their problems by themselves :)
@All
I'm discovering slowly float SSE... I'm not sure on how to save/restore the CPU state in order to use SIMD registers (fxsave (_m515) and fxrstor (_m512) ?), but I wonder how it'll perform. As of now, I'm doing many shuffles to be able to do the right sums, and I guess I should build a new workflow, even if it needs to enforce data length (afaik, YV12 width*height should be MOD4, but I guess there are trickier things to consider).
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.