Menu

Set new existed context and delete the old one

2018-05-31
2018-06-06
  • Siqi Zhuang

    Siqi Zhuang - 2018-05-31

    Hi. I have a Class A where an existed OpenCL context is provided by using viennacl::ocl::setup_context().
    Now I have two Class A objests, says b and c. The program runs like this:
    1. construct b
    2. run b
    3. destruct b
    4. construct c
    5. run c
    6. destruct c

    But I found that setting context in c always fails. I had a warning in debug mode:

    ViennaCL: Warning in init_context(): Providing a list of devices has no effect, because context for ViennaCL is already created!

    I wonder how to elegantly solve this problem. I'd prefer manually delete the context in my class destructor so that I don't need check viennacl context every time since it should be clear.

     

    Last edit: Siqi Zhuang 2018-05-31
  • Siqi Zhuang

    Siqi Zhuang - 2018-05-31

    By the way, I have to pass cl_mem objects to viennacl::compressed_matrix<cl_float>.
    In object c, program crashes when running to this line because of the context problem:

        viennacl::compressed_matrix<cl_float>  *vcl_sparse_matrix = new viennacl::compressed_matrix<cl_float>((*buf_node2NBRAddress)(), (*buf_node2NBRCol)(),
            (*buf_matValueL)(), nbBlockNodes, nbBlockNodes, tolMatElementNum);
    
     

    Last edit: Siqi Zhuang 2018-05-31
  • Siqi Zhuang

    Siqi Zhuang - 2018-05-31

    I figure out a way to solve this problem. I check the current context id in the initialization of ViennaCL. Then I add a new context and switch to that context.

      long current_context_id = viennacl::ocl::backend<false>::current_context_id();
      viennacl::ocl::setup_context(current_context_id + 1, m_context(), m_devices[0](), m_queue());
      viennacl::ocl::switch_context(current_context_id + 1);
    

    But I don't really like this way. Can I delete the context in my class destructor by myself, so that each time when I run the object, I just need to set the context in context id 0 ?

    And one more thing. Since it won't release context resource, there could be some problem when I close the software (like "program stopped working" in windows ).
    Specifically, when exiting the software that I'm developping, it would clear some gpu memory in the first place. After that is the automatic destructing process of ViennaCL, which causes repetitive release of some resource and leading to crash. I tried only use one line

    viennacl::ocl::setup_context(current_context_id + 1, m_context(), m_devices[0](), m_queue());
    

    And this also causes the crash after my exiting the software. So I really need a method to explicitly release all the resouces used by ViennaCL and avoid repetitive memory release. Could you help me?

     

    Last edit: Siqi Zhuang 2018-05-31
  • Siqi Zhuang

    Siqi Zhuang - 2018-06-01

    Currently I add following codes in backend.hpp

      static void delete_context() {
        initialized_.clear();
        contexts_.clear();
        current_context_id_ = 0;
      }
    

    I call this function in my class destructor so as to release the static contex member. After doing this, it won't cause crash after my software exits. I'll keep watching.

     
  • Karl Rupp

    Karl Rupp - 2018-06-01

    Hi Siqi,
    as you've observed, ViennaCL isn't good at freeing contexts. The context is modeled as a singleton that hovers in the background. Your workaround is fine and reasonable.
    Best regards,
    Karli

     
  • Siqi Zhuang

    Siqi Zhuang - 2018-06-05

    Hi. After adding

      static void delete_context() {
        initialized_.clear();
        contexts_.clear();
        current_context_id_ = 0;
      }
    

    in backend.hpp, and the program run this way:
    1. construct b
    2. run b (use viennacl::linalg::solve())
    3. destruct b
    4. construct c
    5. run c (use viennacl::linalg::solve())
    6. destruct c

    Sadly I found that program crashes when running to the viennacl::linalg::solve() function in Step 5.
    But if I don't use delete_context() in the destructor of b (step 3), it won't crash.
    It's interesting since I give c a new cl_context and therefore a new viennacl context. I don't know if there are conections between something in b and something in c.

    I suppose there are some program cache or something else defined or set in b that affects something in c and causes the crash.

     
  • Karl Rupp

    Karl Rupp - 2018-06-05

    Is it possible for you to provide a minmal example that reproduces the issue? This would make it much easier for me to say what is going wrong.

     
  • Siqi Zhuang

    Siqi Zhuang - 2018-06-05

    This issue is very strange. It only occurs when I embed the codes to software. Strangely when I run my console program, it won't crash. The software don't use ViennaCL except for this piece of code. Theoretically speaking, it should be same when I run console or the software run the code. And I can't debug the software since I don't have source code. That's the reason why I can't really locate the issue...

    One thing reproduces the issue is clearing contexts_ in backend.hpp
    But if I don't clear the contexts_, software would crash after exiting...

    In Class A as I said above, the OpenCL initializing codes look like this:
    (the m_xxx variates are global in class A)

      cl::Platform::get(&m_platforms);
      cl::STRING_CLASS str;
    
      for (int i = 0; i < m_platforms.size(); i++) {
        m_platforms[i].getInfo(CL_PLATFORM_VENDOR, &str);
        std::cout << i << " :" << str << std::endl;
        if ((str.find("NVIDIA") != str.npos) || (str.find("AMD") != str.npos)) {
          m_platformId = i;
          printf("use platform id = %d\n", m_platformId);
        }
      }
    
      cl_context_properties properties[] =
      { CL_CONTEXT_PLATFORM, (cl_context_properties)(m_platforms[m_platformId])(), 0 };
      m_context = cl::Context(CL_DEVICE_TYPE_GPU, properties);
      m_devices = m_context.getInfo<CL_CONTEXT_DEVICES>();
      m_queue = cl::CommandQueue(m_context, m_devices[0]);
    
      // setup viennacl context
        long current_context_id = viennacl::ocl::backend<>::current_context_id();
        viennacl::ocl::setup_context(current_context_id + 1, m_context(), m_devices[0](), m_queue());
        viennacl::ocl::switch_context(current_context_id + 1);
    

    As showed above. The class object b and c will construct their own cl_context and pass it to ViennaCL

    I delete the contexts_ in backend.hpp in this way:

      static void delete_context() {
        initialized_.clear();
        contexts_.clear();
        current_context_id_ = 0;
      }
    

    or this way:

      static void delete_context() {
        initialized_[current_context_id_] = false;
        contexts_.erase(current_context_id_);
      }
    

    The viennacl::linalg::solve() will all crash in step 5.

     
  • Siqi Zhuang

    Siqi Zhuang - 2018-06-05

    I create cl_context and pass it to viennacl.
    Then I ran kernels both in my program and math function in viennacl.
    When I release this context, how could I perfectly relase all resources of viennacl related to this context?

     
  • Siqi Zhuang

    Siqi Zhuang - 2018-06-06

    I found that the error message in crash point is
    ViennaCL: Could not find program 'float_vector'

    So after I delete the contexts in b, some programs are deleted? But I set the context in c and switched to that context. Theoretically, all programs should be recompiled.

     

    Last edit: Siqi Zhuang 2018-06-06
  • Siqi Zhuang

    Siqi Zhuang - 2018-06-06

    Now I don't call

      static void delete_context() {
        initialized_.clear();
        contexts_.clear();
        current_context_id_ = 0;
      }
    

    in my class destructor, but in an outer class. The workflow runs like this:
    1. construct b
    2. run b (use viennacl::linalg::solve())
    3. destruct b
    4. construct c
    5. run c (use viennacl::linalg::solve())
    6. destruct c
    ...
    7. delete_context()

    This temporarily solves my crash issue, though I have not figured out the crash reason.

     

Log in to post a comment.