Dispose: performance and best practice

Help
zamirkhan
2010-09-13
2012-12-21
  • zamirkhan

    zamirkhan - 2010-09-13

    I ran a (non-openCL) profiler on my program and noticed that a significant amount of execution time (avg. of 120ms per call) is being spent in ComputeResource.Dispose() and ComputeMemory.Dispose(Boolean).

    Currently I am calling them after every execution/flush of the buffer (strangely I find that executing and flushing the buffer each time is faster than queuing up a large number of executions and then flushing the buffer) on the relevant buffers.

    I'm just wondering if this performance hit is expected and if it is partially avoidable? How often *must* I call dispose?

    Thanks in advance.

     
  • nythrix

    nythrix - 2010-09-13

    I ran a (non-openCL) profiler on my program and noticed that a significant amount of execution time (avg. of 120ms per call) is being spent in ComputeResource.Dispose() and ComputeMemory.Dispose(Boolean).
    120ms per call is quite a lot. Dispose() actually calls into Dispose(bool) so the problem is probably in there. It is a very short method though:

            protected override void Dispose(bool manual)
            {
                if (Handle != IntPtr.Zero)
                {
                    CL10.ReleaseMemObject(Handle);
                    Handle = IntPtr.Zero;
                }
            }
    

    The only suspicious place might be the OpenCL function call. I'm not sure though.

    Currently I am calling them after every execution/flush of the buffer (strangely I find that executing and flushing the buffer each time is faster than queuing up a large number of executions and then flushing the buffer) on the relevant buffers.
    I'm not sure I follow you here. By flushing the buffer you mean flushing the command queue?

    I'm just wondering if this performance hit is expected and if it is partially avoidable?
    No it isn't. Maybe there's a problem with the new methods. How are you reading/writing data to/from the buffers?

    How often *must* I call dispose?
    As with all resources you should recycle as much as possible. If, for example, your data change but their size is still the same, create one buffer and then read from and write to it. This is faster than recreating the buffer each cycle (and calling dispose each cycle as well).

    Assuming that you're using C#, what happens if you switch to the "using" construct?

     
  • zamirkhan

    zamirkhan - 2010-09-13

    120ms per call is quite a lot. Dispose() actually calls into Dispose(bool) so the problem is probably in there. It is a very short method though:
    You are right, it seems that almost all of that time can be attributed to Dispose(bool).

    I'm not sure I follow you here. By flushing the buffer you mean flushing the command queue?

    Yes. Experimentally, calling Queue.Flush() after every Queue.Execute runs faster than calling Flush after queuing up many executions (which to me is counter-intuitive).

    No it isn't. Maybe there's a problem with the new methods. How are you reading/writing data to/from the buffers? As with all resources you should recycle as much as possible. If, for example, your data change but their size is still the same, create one buffer and then read from and write to it. This is faster than recreating the buffer each cycle (and calling dispose each cycle as well).

    Currently I am creating a new ComputerBuffer each time I have new data. They are indeed of the same size, but it's not clear to me how to write new values to the existing buffer. The only place I can seem to supply the data is in the constructor. What am I missing?

    Assuming that you're using C#, what happens if you switch to the "using" construct?
    The performance is unaffected.

     
  • nythrix

    nythrix - 2010-09-13

    Check ComputeCommandQueue.ReadFromBuffer() and WriteToBuffer() methods. There are similar methods for working with images. See if that makes any difference.

    I found out that the reason behind the slowdowns in Dispose(bool)'s are the CL10.ReleaseWhatever(Handle) calls. Not sure why this happens, although I'm sure there's not much I can do about it. Cloo only goes that far.

     
  • zamirkhan

    zamirkhan - 2010-09-13

    The WriteToBuffer() method allows me to replace the Dispose, but the overall timing appears to be unaffected, even though WriteToBuffer is reportedly averaging 60ms.

     
  • nythrix

    nythrix - 2010-09-13

    Depending on buffer size, source memory area, destination memory area and mode of operation, data transfers need some time to finish. This is definitely much more familiar (and expectable) than the Dispose scenario.
    For comparison: Reading a 2MB buffer from OpenCL memory (of a CPU device) to "normal" RAM takes about 3ms in my oldish notebook (ATI Stream v2.2). A buffer twice as big doubles the read time. Profiling adds about 10% to the figures.

    All of the resulting times can be tracked down to the drivers. As far as I can tell, the method with the highest overhead inside Cloo takes about as long as the Console.WriteLine() method.

     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks