Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

FFT Get Buffer size failure for short FFT's

rogerscm
Beginner
1,062 Views
Product: IPP 4.0 for Linux

When trying to specify and allocate a working buffer for an FFT, the returned buffer size from ippsFFTGetBufSize is 0 when the order of the FFT is <= 10. It's also only 7 bytes for an order of 11. Is this the expected performance?

The code is as follows:

if(ippError==ippStsNoErr)
{
ippError = ippsFFTGetBufSize_C_32f(pFFTSpec->pFFTSpec,&Size);

printf("Buffer size %d Error %d ", Size, ippError);

if(ippError==ippStsNoErr)
{
pFFTSpec->pBuffer = ippsMalloc_8u(Size);
if(!(pFFTSpec->pBuffer))
dspError = dspStsMemAllocErr;
}
}

It all compiles correctly, and no errors are returned.

Thanks for any comments.
0 Kudos
9 Replies
Vladimir_Dudnik
Employee
1,062 Views
Hi,
it is expected behaviour of functions. Actually additional buffer is not needed in all cases, so in such cases this function will return zero as size of buffer.
Regards,
Vladimir
0 Kudos
w32
Beginner
1,062 Views
In my opinion, this behaviour should be described in IPPs documentation. Because it is not obviously and not mentioned in the doc.
I have diddled three days in searching bug in my code until found this topic.

0 Kudos
levicki
Valued Contributor I
1,062 Views
if(ippError==ippStsNoErr)

Since people come here to learn, let me add something to common knowledge:

  • It is an ugly and error prone habit to nest if blocks which use the same error variable
  • Another ugly habit is to leave out spaces between if and left parenthesis -- if is not a function call, it is a language keyword.
  • Space should be written after "," too, just like it is done in the plain text.
  • No spaces around operators can lead to errors like this one:

#include 

static int div(int *divisor) // Pointer to the divisor
{
	int result=5; // Dividend

	result=result/*divisor;     /* Do divide */;
	*divisor=l;
	return (result);
}

int main()
{
	int num = 5; // Divisor
	std::cout << "Division " << div(&num) << std::endl;
	return (0);
}

Moreover, if you invert your error testing logic, you will have less to indent:

	if (ippError != ippStsNoErr) {
		// abort execution or whatever
	}

	ippError = ippsFFTGetBufSize_C_32f(pFFTSpec->pFFTSpec, &Size);

	if (ippError != ippStsNoErr) {
		// abort execution or whatever
	}

	pFFTSpec->pBuffer = ippsMalloc_8u(Size);

	if (pFFTSpec->pBuffer == NULL) {
		// abort execution or whatever
	}

That way you will have the code which is much easier to read and maintain.

0 Kudos
Vladimir_Dudnik
Employee
1,062 Views

Thank you Igor, I'm agree with what you suggested

Vladimir

0 Kudos
w32
Beginner
1,062 Views
IgorLevicki:


if (ippError != ippStsNoErr) {
// abort execution or whatever
}

ippError = ippsFFTGetBufSize_C_32f(pFFTSpec->pFFTSpec, &Size);

if (ippError != ippStsNoErr) {
// abort execution or whatever
}

pFFTSpec->pBuffer = ippsMalloc_8u(Size);

if (pFFTSpec->pBuffer == NULL) {
// abort execution or whatever
}



This is not good code. Because on Intel Celeron D with long pipeline and short cache this code will re-init pipeline on every false if and decrease performance.
0 Kudos
Vladimir_Dudnik
Employee
1,062 Views

I'm not coompletely agree with that. You should care about processor pipeline in tight internal loops, where the actual work is done.

I do not think it is important for initialization code.

In any case, do you think you can get more than 1% performance improvement in that particular case?

You know, it is always tradeoff. Quite optimal code can be very difficult to read and maintain, so you needto choose where you need paid for that and where it might have no sense

Valdimir

0 Kudos
w32
Beginner
1,062 Views
vdudnik:

I do not think it is important for initialization code.



You are right it's not important for init blocks.

vdudnik:

In any case, do you think you can get more than 1% performance improvement in that particular case?



The same code with falsed logic "if" operators in computation code work better on AMD Semprone than on equivalent Intel Celeron D. Better on 3-5%.

vdudnik:

You know, it is always tradeoff. Quite optimal code can be very difficult to read and maintain, so you needto choose where you need paid for that and where it might have no sense


Yes, it's matter of taste.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,062 Views

If an additional buffer is NOT required, then how is the pointer to the buffer treated?

Must the initialization code NULL the pointer and then use that as an indication not to free the (non-)buffer?

Jim

0 Kudos
w32
Beginner
1,062 Views
JimDempseyAtTheCove:

Must the initialization code NULL the pointer and then use that as an indication not to free the (non-)buffer?

NULL pointer initialization is a good practical work. You should initialize pointer to NULL, than receive buffer size and allocate memory if its necessary (size!=0). You should free buffer after calculation.

P.S.:
Any FFT functions check pointer to NULL and work correctly without buffer. Buffer is required only for speed up code due to decreasing memory allocation process.
P.P.S.:
You can set NULL instead pointer always, FFT functions allocate memory internally if it is necessary. This is not decrease performance of computation if you call FFT rarely.
0 Kudos
Reply