View Full Version : Help with Avisynth filter dev
redfordxx
9th December 2006, 16:49
Where can I get description of Avisynth's classes? The avisyth homepage is down...
Moreover I have folowing problem:
VirtualDub writes
AvisSynth read error: CAVIStreamSynth: System exception - Access violation
I think it appeared after I wrote something like this:
unsigned char *pDiff01;
pDiff01 = (unsigned char * const) malloc(src_pitch*src_height*4);
Then I commented almost everything, so only plane copy remained...and the exception.
Do you see what I am missing?
redfordxx
9th December 2006, 16:52
this is my cpp (MS VS60)
#include <stdlib.h>
#include <malloc.h>
#include "windows.h"
#include "avisynth.h"
class RedSizer : public GenericVideoFilter {
long Parametr;
// unsigned char *pDiff01;//, *pDiff10, *pDiff11, *pDiff1_1;
// unsigned char *pCopySource;
int ProcessPlane(int src_pit, int dst_pit, int rowsize, const BYTE* srcp, BYTE* dstp, int height);
PVideoFrame GetFrame_YV12(int inFrame, IScriptEnvironment* env);
public:
RedSizer(PClip _child, long _Par, IScriptEnvironment* env):GenericVideoFilter(_child)
{
Parametr=_Par;
// PVideoFrame src = child->GetFrame(0, env); // Request frame 'inFrame' from the child (source) clip.
// const int src_pitch = src->GetPitch(PLANAR_Y); // Requests pitch (length of a line) of the destination image. // For more information on pitch see: http://www.avisynth.org/index.php?page=WorkingWithImages // (short version - pitch is always equal to or greater than width to allow for seriously fast assembly code)
// const int src_height = src->GetHeight(PLANAR_Y); // Requests the height of the destination image.
// pDiff01 = (unsigned char * const) malloc(src_pitch*src_height);
// pDiff10 = pDiff01 +src_pitch*src_height;//(unsigned char * const) malloc(dst_pitch*dst_height);
// pDiff11 = pDiff10 +src_pitch*src_height;//(unsigned char * const) malloc(dst_pitch*dst_height);
// pDiff1_1 =pDiff11 +src_pitch*src_height;//(unsigned char * const) malloc(dst_pitch*dst_height);
}
~RedSizer();
PVideoFrame __stdcall GetFrame(int inFrame, IScriptEnvironment* env);
};
/*******************************************************************************************************************************************/
RedSizer::RedSizer(PClip _child, long _Par, IScriptEnvironment* env);// : GenericVideoFilter(_child), Par(_Par){//}
RedSizer::~RedSizer() {
// free(pDiff01);
}
int RedSizer::ProcessPlane(int src_pit, int dst_pit, int rowsize, const BYTE* srcp, BYTE* dstp, int height)
{
int w, h;
/*
for (h=1; h < height-1;h++) {
for (w = 0; w < rowsize-1; w++)
// *(pDiff01 + w+h*src_pit) = (*(srcp + w+h*src_pit)- *(srcp + w+(h+1)*src_pit))/2+128; // Calculate differences
// *(pDiff01+src_pit*height + w+h*src_pit) = (*(srcp + w+h*src_pit)- *(srcp + w+1+(h)*src_pit))/2+128; // Calculate differences
// *(pDiff01+src_pit*height*2 + w+h*src_pit) = (*(srcp + w+h*src_pit)- *(srcp + w+1+(h+1)*src_pit))/2+128; // Calculate differences
// *(pDiff01+src_pit*height*3 + w+h*src_pit) =(*(srcp + w+h*src_pit)- *(srcp + w+1+(h-1)*src_pit))/2+128; // Calculate differences
}
*/
for (h=0; h < height;h++) { // Loop from top line to bottom line
for (w = 0; w < rowsize; w++) // Loop from left side of the image to the right side.
*(dstp + w+h*src_pit) = *(srcp+w+h*src_pit); // Copy each byte from source to destination.
// *(dstp + w+h*src_pit) = *(pDiff01+w+h*src_pit);
// *(dstp + w+h*src_pit) = *(pDiff01+src_pit*height+w+h*src_pit);
}
return 0;
}
PVideoFrame RedSizer::GetFrame_YV12(int inFrame, IScriptEnvironment* env) {
// This is the implementation of the GetFrame function for YV12.
PVideoFrame src = child->GetFrame(inFrame, env); // Request frame 'inFrame' from the child (source) clip.
PVideoFrame dst = env->NewVideoFrame(vi); // Construct a frame based on the information of the current frame // contained in the "vi" struct.
const unsigned char* srcp = src->GetReadPtr(PLANAR_Y); // Request a Read pointer from the source frame. // This will return the position of the upperleft pixel in YUY2 images,
unsigned char* dstp = dst->GetWritePtr(PLANAR_Y); // Request a Write pointer from the newly created destination image.
const int dst_pitch = dst->GetPitch(PLANAR_Y); // Requests pitch (length of a line) of the destination image. // For more information on pitch see: http://www.avisynth.org/index.php?page=WorkingWithImages // (short version - pitch is always equal to or greater than width to allow for seriously fast assembly code)
const int dst_width = dst->GetRowSize(PLANAR_Y); // Requests rowsize (number of used bytes in a line.
const int dst_height = dst->GetHeight(PLANAR_Y); // Requests the height of the destination image.
const int src_pitch = src->GetPitch(PLANAR_Y);
const int src_width = src->GetRowSize(PLANAR_Y);
const int src_height = src->GetHeight(PLANAR_Y);
ProcessPlane(src_pitch, dst_pitch, dst_width, srcp, dstp, dst_height);
/*
const int dst_pitchUV = dst->GetPitch(PLANAR_U); // The pitch,height and width information
const int dst_widthUV = dst->GetRowSize(PLANAR_U); // is guaranted to be the same for both
const int dst_heightUV = dst->GetHeight(PLANAR_U); // the U and V planes so we only the U
const int src_pitchUV = src->GetPitch(PLANAR_U); // plane values and use them for V as
const int src_widthUV = src->GetRowSize(PLANAR_U); // well
const int src_heightUV = src->GetHeight(PLANAR_U); //
srcp = src->GetReadPtr(PLANAR_U);
dstp = dst->GetWritePtr(PLANAR_U);
ProcessPlane(src_pitchUV, dst_pitchUV, dst_widthUV, srcp, dstp, dst_heightUV);
srcp = src->GetReadPtr(PLANAR_V);
dstp = dst->GetWritePtr(PLANAR_V);
ProcessPlane(src_pitchUV, dst_pitchUV, dst_widthUV, srcp, dstp, dst_heightUV);
*/
return dst;
}
PVideoFrame __stdcall RedSizer::GetFrame(int inFrame, IScriptEnvironment* env) {
if(vi.IsYV12())
return GetFrame_YV12(inFrame, env);
else
env->ThrowError("Sorry, YV12 only");
// Unreachable
return 0;
}
AVSValue __cdecl Create_RedSizer(AVSValue args, void* user_data, IScriptEnvironment* env) {
return new RedSizer(args[0].AsClip(), args[1].AsInt(0), env);
}
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
env->AddFunction("RedSizer", "c[SIZE]i", Create_RedSizer, 0);
return "`RedSizer' RedSizer plugin";
}
Fizick
9th December 2006, 17:50
http://forum.doom9.org/showthread.php?p=893365#post893365
foxyshadis
9th December 2006, 23:54
Running the avisynth host under the debugger (with your debug-compiled plugin loaded) usually helps sort out these memory access violations pretty quickly. It should break when it encounters an exception inside your code.
redfordxx
10th December 2006, 00:33
Running the avisynth host under the debugger (with your debug-compiled plugin loaded) usually helps sort out these memory access violations pretty quickly. It should break when it encounters an exception inside your code.
That's bad. I wondered how to debug dll in Avisynth...
You know, three days ago I installed VC++ first time. I mean I used C first time ever (I used to do some stuff in Pascal or Visual Basic where debuging was easy for me). I don't know know about debug-compiling.
If that is possible shortly explain I would appreciate. Maybe it is only an option to set...
Guest
10th December 2006, 01:20
I built your code as posted above and it did not crash. The filter as posted doesn't do anything useful but it does not crash.
If you want help with it, post your entire build directory (zipped up).
You aren't using the parameter, so I just tried:
RedSizer()
redfordxx
10th December 2006, 03:18
If you want help with it, post your entire build directory (zipped up).
Thanks for your concern, neuron2,
so this is it,
there are few files you just have to rename to *.cpp to follow what happened here:
First I built with file which is now renamed to Redsizer.cpp1 ... OK
Then file Redsizer.cpp2...Exception
Then again file Redsizer.cpp1...Exception
Then I deleted all files in the directory except source....worked
Then again file Redsizer.cpp2...OK
Then the current file Redsizer.cpp...Exception
And the only difference is uncommenting lines around 122, declaring dDiff-variables and replacing pDiff11,pDiff10,pDiff01 on line 143
foxyshadis
10th December 2006, 04:00
I can't find any screenshots of VS6, but I think it has a build debug in the build menu? Or you might have to change it in the project settings. In VS7 and 8 there's a dropdown so you can change with at any time.
Then again, it should default to debug build, so it might not be in release mode at all.
Anyway, this cries out for screenshots (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/debughm.asp), but it's the official debugger documentation, and this is the user's guide (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcug98/html/_asug_Home_Page.3a_.Debugger.asp) for it.
Here's a screenshot (http://www.cs.tau.ac.il/faq/images/debug2.png) of where you add the debugging info. Put the path to virtualdub in the top, and the path to your script (in quotes) in the arguments box.
Also be sure to clean and rebuild, with the host closed, if you suspect it's just not recompiling for some reason. VS is pretty buggy, especially VS6 before the service packs.
Guest
10th December 2006, 04:13
so this is it See here for the procedure for debugging Avisynth filters:
http://forum.doom9.org/showthread.php?p=784386#post784386
EDIT: You are writing outside your malloc'ed memory:
*(pDiff11 + w+h*src_pit) = (*(srcp + w+h*src_pit)- *(srcp + w+1+(h+1)*src_pit))/2+128;
I proved it in the debugger. I can't fix it for you because you didn't put comments and I don't know what your intent is, but you ought to be able to take it from here. Maybe this comment will help: if your size is h, then the last line you can write is h-1.
redfordxx
10th December 2006, 05:33
I had First-chance exception in VirtualDub.exe (KERNEL32.DLL): 0xE06D7363: Microsoft C++ Exception.
but the problem was not in the cycle (the boundaries are OK) but in the malloc directly.
I bet I had there
pDiff01 = (unsigned char * const) malloc(src_pitch*src_height*4);
and it didn't work but after this trying and commenting I ended with
pDiff01 = (unsigned char * const) malloc(src_pitch*src_height);
The debugger for me stopped somewhere outside the project. It can signify that I write out?
redfordxx
10th December 2006, 05:35
Thanks much for the debugging how-to.
Guest
10th December 2006, 05:49
Set a breakpoint on ProcessPlane() and then step through it. It crashes on the line I posted above.
foxyshadis
10th December 2006, 06:05
You might be interested to know that newer compilers usually generate more efficient code for array access than pointer access. Not always, and the extent depends on the compiler (if you ever target ICL, it's extremely important). I don't know about VC6, since I used borland builder before switching to VC8 & gcc.
redfordxx
10th December 2006, 12:22
efficient code for array access than pointer access. Not always, and the extent depends on the compiler (if you ever target ICL, it's extremely important). I don't know about VC6
So I cannot make decision here, because I will not upgrade. (only if somebody else can confirm)
Only thing I could rely on is that if the filter will be really useful someone else will compile/optimize.;)
But on the other hand, it can be more readable and maybe smaller chance of exceptions for me;)
What is ICL?
BTW: When speaking about efficiency. I will perform a calculation of difficult formula. To make it more readable and changable it's better to make it as 2 or 3 function calls inside each other. But I expect it could be slower. When I set compiler optimize for speed, will this be solved?
redfordxx
10th December 2006, 12:56
I start to like the array idea, but there are two things I dont know
- how to dynamically allocate arrays (only after I know the pitch and height)
- how to access planes as arrays too..
foxyshadis
10th December 2006, 13:30
You don't have to declare an array to use it. Just take the pointer you just allocated and start putting [x] on it. You will have to increment the pointer for height though; see, for instance, EEDI2's loops. gcc supports multidimensional array redefinition, but that doesn't pertain here.
Most compilers will inline any quick and dirty function, when you allow them to. (See code generation, I think.) Sticking __inline or even __forceinline provides a stronger hint that you really do want it inlined, regardless of how much smarter than you it thinks it is. If all else fails, use a macro. (You should see the several-hundred line macros in ffmpeg.)
squid_80
10th December 2006, 15:17
Just take the pointer you just allocated and start putting [x] on it. You will have to increment the pointer for height though; see, for instance, EEDI2's loops.
What's wrong with srcp[height*pitch+width] ?
Guest
10th December 2006, 15:24
What's wrong with srcp[height*pitch+width] ? Multiplications are expensive. It's better to bump the pointer by the pitch at the end of the height loop.
squid_80
10th December 2006, 15:43
If you want to be absolutely positive yes, but if it's inside a loop that increments height the compiler should be smart enough to do it that way anyway.
Then again one of the VS2005 betas had a bug with this so I guess it is better safe than sorry.
Guest
10th December 2006, 15:49
I still use VC 6 so I don't rely on it being smart. :)
That's what the OP uses, too.
redfordxx
11th December 2006, 11:32
Well so what should I do?
Anyway it seems to me that if using arrays, it makes sense to access it as srcp[h][w].
I have to add, if that's important, that the calculations I make are usually combinations of several pixels in square area, so it's more like srcp[h+j][w+i]
redfordxx
11th December 2006, 11:43
One more concerning function calls:
When I write:BYTE aPlane(int h, int w){
return(*(srcp+h*pitch+w));
}
...
*(dstp+h*pitch+w)=aPlane(h-1,w-1)-aPlane(h-0,w-0)+aPlane(h+1,w+1); or *(dstp+h*pitch+w)=*(srcp+(h-1)*pitch+w-1)-*(srcp+h*pitch+w)+*(srcp+(h+1)*pitch+w+1); I suppose the second case is faster.
But does the compiler make it same? (the faster version)
Is this issue related to the word you used: inline?
squid_80
11th December 2006, 11:45
It won't let you use a pointer as a two dimensional array, only one-dimensional. That's why foxyshadis was talking about multidimensional array redefinition - if it was available you could do it.
IanB
11th December 2006, 13:03
@redfordxx,
Your 1st example is certainly more compact and readable. And as long as the function aPlane is 'inline'able (You don't have to declare it __inline for it to be 'inline'able, but it helps) the 2 representation should compile to pretty much the same code. [From VC4 M$ compilers really like to inline things all by themself.]
If you just want to access 3 source pixels and write 1 dest pixel per frame this code is adaquate. However if you wish to scan the entire plane this is a pretty slow way to go.
An optimising compiler will probably recognise the multiply by pitch as related to only the outer loop and move the multiply outside the inner loop, but it almost certainly will not be able to see the relationship between pitch and width so the multiplies will remain.
You as a human have greater knowledge of the code and the relationship between width and pitch hence should be able to write code without the multiplies.
If you are serious about performance always ask for an assembler listing from the compiler and check what was generated.
Look at the avisynth source for examples of parsing frames quickly.
foxyshadis
11th December 2006, 13:12
That's why I suggested looking at EEDI2, although I'm sure a lot of pure C plugins are similar. Stripping out the multithreading I added:
unsigned char *srcp, *srco = src.GetPtr(plane);
unsigned char *dstp, *dsto = msk.GetPtr(plane);
const int height = src.GetHeight(plane);
const int width = src.GetWidth(plane);
const int src_pitch = src.GetPitch(plane);
const int dst_pitch = msk.GetPitch(plane);
unsigned char *srcpp;
unsigned char *srcpn;
for (int y=1; y<height-1; ++y)
{
srcp = srco+src_pitch*y;
dstp = dsto+dst_pitch*y;
srcpp = srcp-src_pitch;
srcpn = srcp+src_pitch;
for (int x=1; x<width-1; ++x)
{
if ((abs(srcpp[x]-srcp[x]) < 10 && abs(srcp[x]-srcpn[x]) < 10 &&
abs(srcpp[x]-srcpn[x]) < 10) ||
(abs(srcpp[x-1]-srcp[x-1]) < 10 && abs(srcp[x-1]-srcpn[x-1]) < 10 &&
abs(srcpp[x-1]-srcpn[x-1]) < 10 && abs(srcpp[x+1]-srcp[x+1]) < 10 &&
abs(srcp[x+1]-srcpn[x+1]) < 10 && abs(srcpp[x+1]-srcpn[x+1]) < 10))
continue;
... etc
}
}
Instead of long chains of pointers that are going to boggle your mind when you come back to maintain it. Basically, it uses a local variable for each line of source it'll access, *p and *n substituting for [y-1] and [y+1]. There are probably even better examples out there.
The original source relies on this construct instead, which isn't easy to make threadsafe with OpenMP:
dstp += dst_pitch;
srcpp += src_pitch;
srcp += src_pitch;
srcpn += src_pitch;
initializing everything beforehand. Perfectly valid for single-threading though. On a decent compiler such changes don't have any effect, but who knows for VC6. For the same reason I can't really comment on your micro-optimization, other than that it's a prime candidate for a macro anyway.
You're right about width and height being involiable, I think tritical only does it for consistency's sake. You could just as easily use vi.height and vi.width, but there's no real performance advantage of doing such. (Only use local variables inside the loop though!)
redfordxx
11th December 2006, 14:09
If you are serious about performance always ask for an assembler listing from the compiler and check what was generated.
Hehe:D:D:D:D
A week ago I knew Visual Basic on "non-expert" level only.
So be nice to me.
IanB
11th December 2006, 15:51
It is a handy skill to be at least able to glean some meaning from the assembly listing with C++ comments. Simple things like what got to be inline code and what didn't. i.e. a block of instructions versus a call statment. Or did some loop invariant code get optimized into the outer loop. i.e. look for the jmp instructions and the target labels.
squid_80
11th December 2006, 16:05
An optimising compiler will probably recognise the multiply by pitch as related to only the outer loop and move the multiply outside the inner loop, but it almost certainly will not be able to see the relationship between pitch and width so the multiplies will remain.
You as a human have greater knowledge of the code and the relationship between width and pitch hence should be able to write code without the multiplies.
Not sure if this is what you mean, but if I compile this code:
int main(char *argv, int argc) {
char *srcp;
char *dstp;
int height=100;
int width=100;
int i, j;
int src_pitch;
int dst_pitch;
for (i=0; i < height; i++) {
for (j=0; j < width; j++) {
dstp[i*dst_pitch+j] = srcp[i*src_pitch+j] + 1;
/* had to put +1 because otherwise smartass compiler uses memcpy */
}
}
return 0;
}
VS2005 spits out this:; 1 : int main(char *argv, int argc) {
push ecx
; 2 : char *srcp;
; 3 : char *dstp;
; 4 : int height=100;
; 5 : int width=100;
; 6 : int i, j;
; 7 : int src_pitch;
; 8 : int dst_pitch;
; 9 :
; 10 : for (i=0; i < height; i++) {
mov ecx, DWORD PTR _srcp$[esp+4]
mov edx, DWORD PTR _src_pitch$[esp+4]
push ebx
push ebp
mov ebp, DWORD PTR _dst_pitch$[esp+12]
push esi
mov esi, DWORD PTR _dstp$[esp+16]
push edi
mov edi, 100 ; 00000064H
$LL6@main:
; 11 : for (j=0; j < width; j++) {
xor eax, eax
npad 6
$LL3@main:
; 12 : dstp[i*dst_pitch+j] = srcp[i*src_pitch+j] + 1;
mov bl, BYTE PTR [ecx+eax]
add bl, 1
mov BYTE PTR [esi+eax], bl
add eax, 1
cmp eax, 100 ; 00000064H
jl SHORT $LL3@main
add ecx, edx
add esi, ebp
sub edi, 1
jne SHORT $LL6@main
pop edi
pop esi
pop ebp
*poof* the multiplication is gone.
redfordxx
11th December 2006, 20:12
Other question:
Now I make all calculations in float. I think it makes it slow. After it will work correctly I want to do it as int as possible. My idea is following, if there is some other "Best practice", pls advice.
Before
float F(float a, float b) {
return ((0.5*a+2*b+1)/3);
}
...
float fValue,f1,f2,a1,a2,b1,b2;
int iValue;
...
f1=F(a1,b1);
f2=F(a2,b2);
fValue=(1/f1+1/f2)/(f1+f2);
iValue=(int) floor(fValue+0.5)
*srcp=(unsigned char)(iValue<1) ? (0) : ((iValue>254) ? (255) : (iValue));
After:
int F(int*divisor, int a, int b) {
int d;
d=*divisor;
*divisor*=6;
return (a+4*b+d);
}
...
float fValue;
int iValue,i1,i2,a1,a2,b1,b2,d1,d2;
...
i1=F(&d1,a1,b1);
i2=F(&d2,a2,b2);
fValue=((float)d1/i1+d2/i2)/(i1/d1+i2/d2);//not sure what are best means to make him calculate in float
iValue=(int) floor(fValue+0.5)
*srcp=(unsigned char)(iValue<1) ? (0) : ((iValue>254) ? (255) : (iValue));
The code does not make much sense, but I hope it can tell the question
Fizick
11th December 2006, 21:43
commont parctice is to scale float to some big integer value,
say 256 or 2048 (not very big)
floor() is very slow (in cycle).
redfordxx
11th December 2006, 22:02
floor() is very slow (in cycle).
what to use instead, if I am still in float?
krieger2005
12th December 2006, 11:45
As i understand Fizick means Fixed-Point-Arithmetic: http://en.wikipedia.org/wiki/Fixed-point_arithmetic
If so, than a floor should be just a set of that bits, which represent the values after the point [5.X] to zero.
redfordxx
13th December 2006, 02:06
commont parctice is to scale float to some big integer value,
say 256 or 2048 (not very big)
Aaah, now I maybe know why I had trouble with the precision of Average plugin. Clouded probably scaled the float not enough (for my purpose). It's in this post (http://forum.doom9.org/showthread.php?p=830935#post830935)
IanB
14th December 2006, 02:49
Your approach using rational arithmetic is a good one. Carrying around aggregate numerator and aggregate denominator means the result is exact until that point, at which you apply 1 single division with the explicit rounding control you wish.int F(int &divisor, int a, int b) { // Use of the alias operator :D
int d=divisor;
divisor *= 6;
return (a+4*b+d); // ((0.5*a+2*b+1)/3
}
...
int nV, dV, iValue,i1,i2,a1,a2,b1,b2;
int d1=1, d2=1; // init rational denom's
...
i1=F(d1, a1, b1);
i2=F(d2, a2, b2);
// ((float)d1/i1+d2/i2)/(i1/d1+i2/d2);
// ( ((d1*i2+d2*i1)/(i1*i2)) / ((i1*d2+i2*d1)/(d1*d2));
// ( ((d1*i2+d2*i1)/(i1*i2)) * ((d1*d2)/(i1*d2+i2*d1));
nV = (d1*i2+d2*i1) * d1*d2;
// ------------------
dV = i1*i2 * (i1*d2+i2*d1);
//iValue = nV/dV; // floor
iValue = (nV + dV>>1)/dV; // round
//iValue = (nV + dV-1)/dV; // ceil
*srcp=(unsigned char)(iValue<1) ? (0) : ((iValue>254) ? (255) : (iValue));Google for "rational arithmetic" also look for the Boost C++ library (used in AVS 3), it has a rational implementation using a rational pair as a class with appropriate operator overloads.
Also floats are not that slow.
Divisions are slow! Both int and float.
So a restructured expression with only 1 divide may help a lot.
redfordxx
17th December 2006, 14:13
Does anyone have an idea why dstp[h*pitch+w]=0 can throw access violation on one clip and not another? The cycle is properly bound and the exception comes somewhere in the second part of the cycle (i.e. when I set the cycle like h<height/2, no problem -- only that half of the image is processed). Sometimes it stops on the line I mentioned, sometimes somewhere inside NTDLL.dll
Guest
17th December 2006, 14:43
Use the debugger to evaluate the resulting pointer versus the bounds of the allocated memory.
foxyshadis
18th December 2006, 01:05
Are you working on a YV12 chroma channel at the time, using the height of the full luma? You definitely don't want to do that.
redfordxx
18th December 2006, 02:30
Ay, problem found. I was blind.
srcpitch!=dstpitch
:devil:
redfordxx
21st December 2006, 14:48
Another questions:
1)When you tell me, this or that is slow or slower... can anybody say some real values so that I have an idea? Like:
x++ is ... times faster than
x+=y which is ... times faster than
z=x+y which is ... times faster than
x*=y which is ... times faster than
z=x*y which is ... times faster than
x/=y which is ... times faster than
z=x/y which is ... times faster than
and all that is ... times faster than float
I assume it is not possible to say it exactly like that, that it depends on other things and that you might discuss among each other about what is true.
But pls gimme at least a clue, so I can decide, when I write the code. Just replace the dots. I even don't know whether it is 2x or 10x or whatever.
2) And you advice me also, to "ask for an assembler listing from the compiler and check what was generated"... So where can I find some documentation for MS VC++ inline asm. Most important is the description of instruction.
Guest
21st December 2006, 15:40
http://www.agner.org/optimize/
http://www.cortstratton.org/articles/OptimizingForSSE.php
So where can I find some documentation for MS VC++ inline asm. Most important is the description of instruction.
Google. I found these in 10 seconds for AMD:
http://developer.amd.com/documentation.jsp
http://www.amd.com/us-en/Processors/DevelopWithAMD/0,,30_2252_11395_11428,00.html
redfordxx
27th December 2006, 13:52
Assume I make dll and there are two filters: A and B. They both use same global variables and functions. When I write script:
source.A.B
will the global variable be shared?
sh0dan
27th December 2006, 15:58
Yes, but it's a very bad practice to use global variables.
1) You cannot have multiple instances of your filter.
2) It breaks multithreading.
What are you trying to accomplish?
redfordxx
27th December 2006, 18:15
What are you trying to accomplish?Well, I want only use global function which will be used by more filters. That's all. So probably from what you said I understand that the good way is to keep all vars within classes and functions and everything should be passes by the function call.
sh0dan
27th December 2006, 18:31
Global _functions_ doesn't have to be bad - they just have to be re-entrant.
*) Global functions are ok, but they have to re-entrant if you want your filter to work with MT.
*) Global variables are BAD. :)
redfordxx
29th December 2006, 15:50
A have a filter which makes series of calculations.
Let's consider this example:
for (...x++){
dstp[x]=a*weight+c;
}
When the filter is called with let's say parameter weight which can be:
0,-1,1,other int,other float
in first three cases there is useless multiplication in the formula (makes it slow). What is the best way to avoid it? This is easy explanatory example --- the situation will be more complex based on mode parameter, which significantly changes the filter behavior.
redfordxx
29th December 2006, 15:50
re-entrantWhat's that?
Guest
29th December 2006, 16:26
What's that?Show a little initiative! You can find out in two minutes by putting this into Google: "reentrant function".
Guest
29th December 2006, 16:30
What is the best way to avoid it? There is no best, per forum rule 12!
foxyshadis
29th December 2006, 22:03
You can always make a macro, or five separate functions by hand, if raw speed is your goal and total maintainability not. See x264's code for a lot of pre-processor abuse in the name of speed.
redfordxx
31st December 2006, 12:00
There is no best, per forum rule 12!
Ok, I'll be more careful with this word;)
I just want to gather some knowledge to avoid going bad direction on crucial crossroads by simliest mistakes, what happened already several times to me.
I learned that there are function pointers, which is something new to me (like all C;))... but maybe that is the way to do the five functions like Foxyshadis said...
If I imagine correctly how it could work, then there is impossible inlining, right? Other options could be use if or switch. A don't see any advantages or disadvantages of any approach but as I am not sure about function pointers, I use switch;) (coz macros I don't understand at all)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.