- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
hi Adriaan van Os,
could you provide a reproducer?(size of buffers you allocated, how you passed pointers and steps, did you perform your src pointer shift to ROI, etc.) GDB output can't help with understanding the root of your issue. Also it is always better (and recommended) to provide an output from ippiGetLibVersion() in order to understand which optimization, ia32 or x64, static or dynamic, threaded or not, which version was working.
const IppLibraryVersion* lib;
lib = ippiGetLibVersion();
printf("%s %s %d.%d.%d.%d\n", lib->Name, lib->Version, lib->major, lib->minor, lib->majorBuild, lib->build);
regards, Igor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Could you try the same (noise==0) with the single-threaded libraries? I'll try to create some reproducer at my side - but there is no any guarantee that my test code will also crash. If you can't provide any reproducer - could you at least provide the full function name and size parameters - width, height, kernel size, step in bytes - in order guaranteed to be on the same page. (otherwise it looks like for looking for a black cat in a dark room, when nobody knows is this cat in this room or not...)
regards, Igor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok, I've taken a look at the sources - there is no internal threading for C1R Wiener functions as well as for ippsMean_32f that is used internally, therefore doesn't matter threaded or not libraries are used (C3, C4, AC4 - have OMP implementation). I don't think that sharing of your GUI code will not help - guess we'll spend more time to build it and make workable at our side. I'll make a small cmd line reproducer and share with you.
regards, Igor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Having your GUI executable I can't see how you use FilterWiener and parameters - I don't think there is any issue in the library - this is too old function that has not been changed for years, it (as all other IPP functions) has several types of tests that are executed with different seeds on the regular basis: algorithmic (of course for all ranges of sizes for roi, mask and noise zero/non-zero), bad-arg, misalignment, mem-bound, thread-safe, special conditions, performance, - on all OSes we support and on all HW we support. Please try the reproducer code below - if you can make this code crash with some legal parameters - please report me back these parameters:
#include <stdio.h>
#include "ipp.h"
static void libInfo( void ){
const IppLibraryVersion *lib;
lib = ippiGetLibVersion();
printf( "Intel(R) Integrated Performance Primitives\n" );
printf( "Wiener filter demo\n" );
printf( "Library IppIP\n" );
printf( "CPU : %s\n", lib->targetCpu );
printf( "Name : %s\n", lib->Name );
printf( "Version : %s\n", lib->Version );
printf( "Build date: %s\n", lib->BuildDate );
}
#define MASK 5
#define WIDTH (640+MASK-1)
#define HEIGHT (480+MASK-1)
int main( ){
int bufSize, srcStep, dstStep, seed = 0;
float noise = 0.0f;
IppStatus status = ippStsNoErr;
IppiSize roi, mask, image = {WIDTH,HEIGHT};
IppiPoint anchor;
Ipp32f *pSrc, *pDst, *pImage;
Ipp8u *pBuf;
ippInit();
ippSetCpuFeatures( 0x3F ); /* Atom - S8 code */
mask.width = mask.height = MASK;
anchor.x = mask.width >> 1;
anchor.y = mask.height >> 1;
roi.width = WIDTH - mask.width + 1;
roi.height = HEIGHT - mask.height + 1;
pImage = ippiMalloc_32f_C1( WIDTH, HEIGHT, &srcStep );
pDst = ippiMalloc_32f_C1( roi.width, roi.height, &dstStep );
pSrc = (Ipp32f*)((Ipp8u*)pImage + ( mask.height - anchor.y - 1 ) * srcStep + sizeof(Ipp32f) * ( mask.width - anchor.x - 1 ));
libInfo();
ippiImageJaehne_32f_C1R( pImage, srcStep, image );
ippiAddRandUniform_32f_C1IR( pImage, srcStep, image, 0.0f, 0.1f, &seed );
ippiFilterWienerGetBufferSize( roi, mask, 1, &bufSize );
pBuf = ippsMalloc_8u( bufSize );
status = ippiFilterWiener_32f_C1R( pSrc, srcStep, pDst, dstStep, roi, mask, anchor, &noise, pBuf );
if( status != ippStsNoErr ){
printf( "\nippiWiener function return error status:\n %s\n", ippGetStatusString( status ));
} else {
printf("\nippiWiener detected noise = %f\n", noise );
}
ippiFree( pImage );
ippiFree( pDst );
ippsFree( pBuf );
return 0;
}
how to build: copy this source and ipp headers + ipp static 32-bit libs to some folder:
:wiener iastakh$ gcc -m32 -c wiener_tst.c -o wien.o
:wiener iastakh$ gcc -m32 wien.o libippi.a libipps.a libippvm.a libippcore.a -o wien
:wiener iastakh$ ./wien
Intel(R) Integrated Performance Primitives
Wiener filter demo
Library IppIP
CPU : s8
Name : ippIP Atom (s8)
Version : 9.0.2 (r49912)
Build date: Dec 28 2015
ippiWiener detected noise = 0.092751
uname -a
Darwin xxxxxxxxxx 13.4.0 Darwin Kernel Version 13.4.0: Sun Aug 17 19:50:11 PDT 2014; root:xnu-2422.115.4~1/RELEASE_X86_64 x86_64
regards, Igor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did some more debugging and found the following. The crash disappears when adding dummy references to the following calls (or by instructing ld not to dead-strip those calls)
ippsSum_32s_Sfs, ippsSum_32f, ippsSum_32fc, ippsSum_64f and ippsSum_64fc
So, the bug is that ippFilterWiener is calling variants (or internal code) of those functions (when the noise level is 0.0) in a way that is not compatible with ld's -dead_strip linker option. I assume ippFilterWiener is using a nasty trick to call ownippsSum, otherwise ld would recognize the call. Anyway, as of the Xcode June 2004 release, library code must be compatible with -dead_strip.
Regards,
Adriaan van Os
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Since nobody seems interested in fixing bugs, I will no longer spend time debugging and reporting them.
Regards,
Adriaan van Os
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Adriaan van Os,
IPP works correctly in all other environments - different kinds of Linux, Yocto, QNX, VxWorks, Android, Windows, etc. Therefore I guess that it is XCode ld's -dead_strip linker option bug, not IPPs one. There are no any tricks in calling internal functions. For these particular calls:
IPPFUN( IppStatus, ippiFilterWiener_32f_C1R,( const Ipp32f* pSrc, int srcStep,
Ipp32f* pDst, int dstStep, IppiSize dstRoiSize, IppiSize maskSize,
IppiPoint anchor, Ipp32f noise[1], Ipp8u* pBuffer ))
{
OWN_WIENER_BADARG_TST1( pSrc, srcStep, pDst, dstStep, dstRoiSize, maskSize,
anchor, noise, pBuffer )
{
int width = dstRoiSize.width, height = dstRoiSize.height;
int mw = maskSize.width, mh = maskSize.height, bufStep, h;
Ipp32f shum, *pBuf = NULL, *pLocMean, *pLocVar;
Ipp32f *pV, *pM, min, max;
Ipp32f mpy = 1.f / ( mw * mh ), tmp;
Ipp32f *pS, *pD, *strtSrc, *pS1;
Ipp64f variance = 0;
IppiSize tmpRoi;
int bufSize;
strtSrc = (Ipp32f*)( (Ipp8u*)pSrc - ( mh - anchor.y - 1 ) * srcStep -
sizeof(Ipp32f) * ( mw - anchor.x - 1 ));
tmpRoi.width = width + mw - 1; tmpRoi.height = height + mh - 1;
ippiMinMax_32f_C1R( strtSrc, srcStep, tmpRoi, &min, &max );
max = max - min; max *= max;
bufSize = ALIGN_ON_4_FLOAT( dstRoiSize.width + BUF_JUNK + maskSize.width );
bufSize = bufSize * 4 * sizeof(Ipp32f) + ALIGN_MAGIC;
ippsZero_8u( pBuffer, bufSize );
pBuf = (Ipp32f*)ALIGN_PTR( pBuffer );
bufStep = ALIGN_ON_4_FLOAT( width + mw + BUF_JUNK ) * sizeof(Ipp32f);
pLocMean = pBuf;
pLocVar = (Ipp32f*)( (Ipp8u*)pBuf + 2 * bufStep );
if( wabs( noise[0] ) < IPP_EPS_32F ){/* if the noise variance is not given */
pM = pLocMean; pV = pLocVar;
for( h = 0; h < height; h++ ){
pS = (Ipp32f*)( (Ipp8u*)strtSrc + h * srcStep );
owniLocalVarMean_32f_C1L( pS, srcStep, maskSize, pM, pV,
bufStep, dstRoiSize, h, mpy, 0.f );
ippsMean_32f( pV, width, &tmp, ippAlgHintFast );
pV = (Ipp32f*)( (Ipp8u*)pV + bufStep );
pM = (Ipp32f*)( (Ipp8u*)pM + bufStep );
variance += tmp;
bufStep = -bufStep;
}
if( bufStep < 0 ) bufStep = - bufStep;
shum = (Ipp32f)( variance / height );
noise[0] = shum * mpy / max;
} else {.................
where Sum functions are called from ippsMean:
Ipp32f ownippsMean_32f( const Ipp32f *pSrc, int len, IppHintAlgorithm hint )
{
return (Ipp32f)( ownippsSum_32f( pSrc, len, hint ) / (Ipp64f)len );
}
IPPFUN(IppStatus,ippsMean_32f,(const Ipp32f* __RESTRICT pSrc,int len,Ipp32f* __RESTRICT pMean,
IppHintAlgorithm hint))
{
IPP_BAD_PTR2_RET(pSrc,pMean)
IPP_BAD_SIZE_RET(len)
*pMean = ownippsMean_32f( pSrc, len, hint );
return ippStsNoErr;
}
Regards, Igor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for you reply.
So, we are looking at what seems to be a linker, assembler or compiler bug (in order of increasing probability). I bet it has to do with the compiler trying to inline Ipp32f ownippsMean_32f
{
return (Ipp32f)( ownippsSum_32f( pSrc, len, hint ) / (Ipp64f)len );
}
which can checked by adding __attribute__ ((noinline)) to it.
Regards,
Adriaan van Os
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page