Intel® Embree Ray Tracing Kernels
Discussion forum on the open source ray tracing kernels for fast photo-realistic rendering on Intel® CPU(s)

Memory of acceleration structure - Error Management

Mathieu_L_2
Beginner
494 Views

Actually I'm using embree with custom geometry management. The geometry provided by some random user. For each step of my software I want to know and manage error if some occurs, to give user correct information.

At the begining I was using embree 2.4

My problem  was, when I have a model with a lot of triangle for my system, my software was just exit with no prompt, no catch, no exception when I call rtcCommit.

After some digging, I find that embree 2.10 resolve my problem. But after testing with the provided dll with TBB, or a compiled version with TBB and an other without I still have the same issue.

rtcCommit throw an exception that i can catch, but i still have embree thread running that have issue (Access violation writing location,). So I can't really do a clean error management and my program can't continue, because crash occurs outside my main thread.

Is there a way to check memory usage before a rtcCommit and avoiding unnecessary job to embree? or a possibility to generate accel structure with my main thread.. Or another solution that I can't guess fopr now ? In this section of my code, I d'ont need strong performance, because I only use static scene and this is done once.

 

L.17 call of function where the bug appear

L 92 wild crash appear. Obvsiously I've tested this code with a lot of different geometry of different size, but this one is really big.

http://pastebin.com/tFukmtYC

Thanks for any advice/hint

0 Kudos
4 Replies
SvenW_Intel
Moderator
494 Views

Hi Lagarde,

I tried creating a large scene under Linux and also see the application to get killed during rtcCommit (./viewer -triangle-sphere 5000). I could not find a way to avoid this. In case the memory allocations (like new or mmap) fail, Embree properly returns an error code. However, if the OS decides to kill the application due to too much memory usage there is nothing we can do about. 

rtcCommit should not throw any exception, could you please verify and tell us which exception it is. rtcCommit sets an error code that you can query using the rtcDeviceGetError function.

You can track the memory consumption of Embree during rtcCommit. Therefore register a memory monitor callback function (see here embree.github.com/api.html). Inside this function you can accumulate the total memory consumption of Embree and terminate the BVH build if too much memory is used. You can also check the total memory consumption of your application in that callback and terminate if some limits are reached.

In case this helps, you can also force rtcCommit to only use one thread. Therefore call rtcNewDevice("thread=1") or configure TBB to use only one thread in your application (see Limiting Number of Build Thread section of embree.github.com/api.html).

Regards,

Sven

 

 

0 Kudos
Mathieu_L_2
Beginner
494 Views

Hi Sven,

Thanks you for your answer.


So I did some more digging on the error.

1. rtcCommit and exception throw

Visual Studio, my debugger, catch an "Access violation writing".
I have Multiple error like this before reaching the catch(...) block
of my program (l96 of the pastebin)

This error occur at first, in a embree internal thread and after some step forward(thanks to the debugger),
the main thread detect error in catch block.


When I reach this catch block, I add this lines (not present in the pastbin):


    embreeError = rtcDeviceGetError(NULL);
    if (embreeError != RTC_NO_ERROR)
    {
      LoggerUtils::PushLog(LOGTYPE_ERROR, "rtcNewDevice failed.", VPLOGL_PRETTY_FUNCTION);
      throw std::exception("embree error");
    }
    else
    {
      embreeError = rtcDeviceGetError(_embreeDevice);
      if (embreeError != RTC_NO_ERROR)
      {
        LoggerUtils::PushLog(LOGTYPE_ERROR, "rtcNewDevice failed.", VPLOGL_PRETTY_FUNCTION);
        throw std::exception("embree error");
      }
    }
  


but embreeError == RTC_NO_ERROR.

2. Exit of the application

In  this section I'm guessing because of a Fix found in section 3.

The application exit because, I can't catch and manage an error that occur
in a thread that I don't manipulate. Here, in the internal embree thread.
So because thread is hanging, OS kill the application ?

In my case application doesn't exit, I'm stuck in the debugger.
When I was using embree 2.4 application exit and can't do anything with the debugger.

3. The Fix

If I replace rtcCommit(_embreeScene) by rtcCommitThread(_embreeScene, 0, 1),
the error occur, and I still reach the catch (...) block. However my debugger
isn't looping anymore in embree internal thread, and the program
can continue.

I think this works because rtcCommitThread, use the caller thread to do it's job.
So there isn't any thread stuck.
 


This fix is fine for me now, but I'm a bit disappointed. What do you think of it?


Regards

 

Mathieu

 

---------------- Information ----------------

Embree 2.10 compiled in release mode
    32 bit
    TBB off
    ISPC off
    
My program is compiled in debug mode.
    32 bit
    
My machine is on
    win7 64bit
    I have 16 GB of ram
    Program crash when reaching about 1.5-1.7 GB
    
    

======================================================
Original buggy Method

Parameter:    
    _embreeDevice = rtcNewDevice("thread=1"); //L8 of pastebin
    use of rtcCommit(_embreeScene);
    
    
stacktrace when catch(...) occurs:

--------------- embree thread  ---------------

stack trace:
>    embree.dll!rtcDebug()  + 0x6aa48 bytes    
     [Frames below may be incorrect and/or missing, no symbols loaded for embree.dll]    
     embree.dll!rtcDebug()  + 0x6526e bytes    
     embree.dll!rtcDebug()  + 0x6c7ed bytes    
     embree.dll!embree::TaskScheduler::TaskQueue::execute_local()  + 0x3c bytes    
     embree.dll!embree::TaskScheduler::threadIndex()  + 0x19f bytes    
     embree.dll!embree::TaskScheduler::threadIndex()  + 0x345 bytes    
     embree.dll!embree::TaskScheduler::threadIndex()  + 0x3f bytes    
     embree.dll!rtcDebug()  + 0x75a3a2 bytes    
     kernel32.dll!BaseThreadInitThunk()  + 0x12 bytes    
     ntdll.dll!RtlInitializeExceptionChain()  + 0x63 bytes    
     ntdll.dll!RtlInitializeExceptionChain()  + 0x36 bytes    

disassembly:
    not really readable for me but can't step foward with the debugger
    
Message provided by Visual Studio:
    Exception thrown at 0x04fc4928 (embree.dll) in CLEAViewer.exe: 0xC0000005: Access violation writing location 0x00000000.

    If there is a handler for this exception, the program may be safely continued.


--------------- My program thread  ---------------

stack trace:
     embree.dll!rtcDebug()  + 0x6aa48 bytes    
     [Frames below may be incorrect and/or missing, no symbols loaded for embree.dll]    
     embree.dll!rtcDebug()  + 0x6526e bytes    
     embree.dll!rtcDebug()  + 0x6c7ed bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x86 bytes    
     embree.dll!embree::TaskScheduler::TaskQueue::execute_local()  + 0x3c bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x13c bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!rtcDebug()  + 0x54ea8 bytes    
     embree.dll!rtcDebug()  + 0xdc64b bytes    
     embree.dll!rtcDebug()  + 0x77e5b bytes    
     embree.dll!ISPCSync()  + 0x127d0 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x86 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x86 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x86 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!ISPCSync()  + 0x12550 bytes    
     embree.dll!rtcUpdateBuffer()  + 0x1d5e bytes    
     embree.dll!rtcDebug()  + 0x128b bytes    
     embree.dll!embree::TaskScheduler::TaskQueue::execute_local()  + 0x3c bytes    
     embree.dll!rtcUpdateBuffer()  + 0xd5d bytes    
     embree.dll!rtcUpdateBuffer()  + 0x1c68 bytes    
     embree.dll!rtcCommit()  + 0xb2 bytes    
>    CLEARenderLib.dll!CPUScene::GenerateEmbreeScene()  Line 289 + 0xd bytes    C++
     CLEARenderLib.dll!CPUScene::Initialize()  Line 69 + 0x8 bytes    C++
     CLEARenderLib.dll!ViewManager::PostInitialize()  Line 120 + 0x1a bytes    C++
     CLEARenderLib.dll!WindowManager::Initialize()  Line 104 + 0xb bytes    C++
     CLEARenderLib.dll!OutputEngine::Initialize()  Line 20 + 0x12 bytes    C++
     CLEARenderLib.dll!CleaEngine::Initialize()  Line 47 + 0x2b bytes    C++
     [External Code]    
     CLEARenderLib.dll!CLEARendererLib::Engine::INITIALISE_ENGINE_DATA() Line 81 + 0x22 bytes    C++
     CLEAViewer.exe!JSONLoadTest(std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >* path, bool printConfiguration) Line 102 + 0x15 bytes    C++
     CLEAViewer.exe!main(array<System::String^> ^ args) Line 239 + 0x2b bytes    C++
     CLEAViewer.exe!mainCRTStartupStrArray(array<System::String^> ^ arguments) Line 301 + 0x9 bytes    C++

    

disassembly:
    //rtcCommitThread(_embreeScene, 0, 1);
    rtcCommit(_embreeScene);
0FB2C81C  mov         eax,dword ptr [ebp-18h]  
0FB2C81F  mov         ecx,dword ptr [eax+4Ch]  
0FB2C822  push        ecx  
0FB2C823  call        dword ptr [__imp__rtcCommit (0FC71608h)]  
0FB2C829  add         esp,4  

Message provided by Visual Studio:

    Exception thrown at 0x04fc4928 (embree.dll) in CLEAViewer.exe: 0xC0000005: Access violation writing location 0x0170fee0.

    If there is a handler for this exception, the program may be safely continued.


======================================================

 

Hacking Method

Parameter:
    _embreeDevice = rtcNewDevice(NULL); //L8 of pastebin
    use of rtcCommitThread(_embreeScene, 0, 1); //L92 of pastebin
    
stacktrace when catch(...) occurs:

      embree.dll!rtcDebug()  + 0x6aa48 bytes    
     [Frames below may be incorrect and/or missing, no symbols loaded for embree.dll]    
     embree.dll!rtcDebug()  + 0x6526e bytes    
     embree.dll!rtcDebug()  + 0x6c7ed bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x86 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x86 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!rtcDebug()  + 0x54ea8 bytes    
     embree.dll!rtcDebug()  + 0xdc64b bytes    
     embree.dll!rtcDebug()  + 0x77e5b bytes    
     embree.dll!ISPCSync()  + 0x127d0 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x86 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x86 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!embree::TaskScheduler::Task::run()  + 0x86 bytes    
     embree.dll!embree::TaskScheduler::wait()  + 0x5e bytes    
     embree.dll!ISPCSync()  + 0x12550 bytes    
     embree.dll!rtcUpdateBuffer()  + 0x1d5e bytes    
     embree.dll!rtcDebug()  + 0x128b bytes    
     embree.dll!embree::TaskScheduler::TaskQueue::execute_local()  + 0x3c bytes    
     embree.dll!rtcUpdateBuffer()  + 0xd5d bytes    
     embree.dll!rtcUpdateBuffer()  + 0x1c68 bytes    
     embree.dll!rtcCommitThread()  + 0x141 bytes    
>    CLEARenderLib.dll!CPUScene::GenerateEmbreeScene()  Line 288 + 0x11 bytes    C++
     CLEARenderLib.dll!CPUScene::Initialize()  Line 69 + 0x8 bytes    C++
     CLEARenderLib.dll!ViewManager::PostInitialize()  Line 120 + 0x1a bytes    C++
     CLEARenderLib.dll!WindowManager::Initialize()  Line 104 + 0xb bytes    C++
     CLEARenderLib.dll!OutputEngine::Initialize()  Line 20 + 0x12 bytes    C++
     CLEARenderLib.dll!CleaEngine::Initialize()  Line 47 + 0x2b bytes    C++
     [External Code]    
     CLEARenderLib.dll!CLEARendererLib::Engine::INITIALISE_ENGINE_DATA() Line 81 + 0x22 bytes    C++
     CLEAViewer.exe!JSONLoadTest(std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >* path, bool printConfiguration) Line 102 + 0x15 bytes    C++
     CLEAViewer.exe!main(array<System::String^> ^ args) Line 239 + 0x2b bytes    C++
     CLEAViewer.exe!mainCRTStartupStrArray(array<System::String^> ^ arguments) Line 301 + 0x9 bytes    C++

disassembly:
      try
      {
    04B6C814  mov         dword ptr [ebp-4],0  
    04B6C81B  wait  
        rtcCommitThread(_embreeScene, 0, 1);
    04B6C81C  push        1  
    04B6C81E  push        0  
    04B6C820  mov         eax,dword ptr [ebp-18h]  
    04B6C823  mov         ecx,dword ptr [eax+4Ch]  
    04B6C826  push        ecx  
    04B6C827  call        dword ptr [__imp__rtcCommitThread (4CB160Ch)]  
    04B6C82D  add         esp,0Ch  
        //rtcCommit(_embreeScene);
    
Message provided by Visual Studio:    
    Exception thrown at 0x05084928 (embree.dll) in CLEAViewer.exe: 0xC0000005: Access violation writing location 0x0452fce0.

    If there is a handler for this exception, the program may be safely continued.
-------

 

0 Kudos
SvenW_Intel
Moderator
494 Views

Hi Mathieu,

I could reproduce and locate the issue under Windows 32 bit. The problem is that we did not check if _mm_malloc returned nullptr when failing. Please replace the alignedMalloc function in common/sys/alloc.cpp with:

  void* alignedMalloc(size_t size, size_t align) 
  {
    assert((align & (align-1)) == 0);
    void* ptr = _mm_malloc(size,align);

    if (size != 0 && ptr == nullptr) 
      throw std::bad_alloc();
    
    return ptr;
  }

We will have this fixed in the next release.

Sven

 

0 Kudos
Mathieu_L_2
Beginner
494 Views

Hi Sven,

Thanks you for your answer and your time. I have modified the void *alignedMalloc, all works fine.

Thanks again !

0 Kudos
Reply