Open dernasherbrezon opened 3 years ago
This is not a memory leak to worry about and is only shown by Valgrind if explicitly instructed to do so. volk_rank_archs()
which calls volk_load_preferences()
makes sure that the memory is allocated only once:
if (!prefs_loaded) {
n_arch_prefs = volk_load_preferences(&volk_arch_prefs);
prefs_loaded = 1;
}
The memory will be freed by the operating system when the application using volk exists. It would be a “real” memory leak – “Definitely lost” in Valgrind – if the if
guard wasn’t in place (because then a memory allocation would be performed every time a kernel is called).
This “leak” cannot be fixed unless a kind of deinit_volk()
functions is added (and explicitly called).
See [1] for the different leak types in Valgrind (search for “Still reachable”).
[1] https://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.leaks
I thought "memory leak" is a memory that leaked from the control and cannot be freed. Yes, something like deinit_volk()
might be required for this. Or even better: explicit lifecycle management init_volk
and deinit_volk
.
That would bring several benefits:
Currently, you can just add you volk kernel calls to your code and the first time such a function is called, init_volk
is run. With explicit calls to init_volk
and in the end deinit_volk
, we'd add some user complexity. e.g. when an where should GNU Radio call this functions? We can discuss how to add an additional interface to handle this explicitly on demand but I'd like the default to be as is.
Currently, if preferences are not available VOLK defaults to a "use the latest SIMD version available". i.e. prefer AVX over SSE and AVX512 over AVX2, etc.
If VOLK could spit out a warning if it couldn't find a preferences file that would be beneficial.
In terms of predictable performance: The whole init code is called on the very first VOLK kernel call. At that stage, your application is unpredictable in terms of performance because we have no control over CPU internals. Only after a couple of iterations we can start to rely on performance metrics. So, we add a bit more unpredictability into a situation that is already unpredictable.
I know it's less than ideal and we might want to think of a more accessible way but: https://github.com/gnuradio/volk/blob/cb87a41101fc0a754298919c610402512ea3299d/lib/volk_rank_archs.c#L56-L62
I guess we can move this such that we have reliable access to this data structure. And then continue from there. Do you have any suggestions on what to change?
we'd add some user complexity
Agree. This should be carefully introduced. Just wanted to highlight this weird behaviour.
when an where should GNU Radio call this functions?
I'm not writing GNU radio-related application :) But I would assume any application has some kind of lifecycle:
When the code provided as a library it is hard to control how it is going to be used. For example, volk can be used only once briefly and then never executed during application lifecycle.
So yeah. It would be great to modify VOLK such that we can optionally call init and deinit. This should be optional though. Do you have a suggestion how we could achieve this?
Regarding the "volk can be used only once briefly". I agree that this might happen. But it is not the intended use case. VOLK is optimized towards speed for operations that happen frequently.
I thought "memory leak" is a memory that leaked from the control and cannot be freed.
The pointer to the allocated memory is not lost at any time point. If we wanted to, we could release it. However, there is no point doing do so because the memory is used throughout the lifetime of an application. See the definition of “Still reachable” in Valgrind’s documentation [1].
- make application performance predictable. It won't load and parse file on a critical path.
The file is loaded only once. If this is really an issue – I doubt it is in any DSP heavy application – call any kernel once before starting main data processing. If the “unpredictability” of the dispatchers is an issue – once again, I doubt it is – call every used kernel once. Or don’t use unpredictable systems (GNU Radio :wink:) in the first place.
It would be great to modify VOLK such that we can optionally call init and deinit. This should be optional though.
What’s the point if it’s optional and doesn’t provide any benefit? The reported “leak” is not a problem. Even though I suggested how it could be fixed, I don’t think (and never considered) we should. The increased complexity and burden for users of volk is not worth it.
[1] https://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.leaks
The file is loaded only once. [...] Or don’t use unpredictable systems (GNU Radio wink) in the first place.
Are you sure? What about multi-threaded applications. Like GNU Radio. I only had a brief look, but I didn't find any locks.
What’s the point if it’s optional and doesn’t provide any benefit? The reported “leak” is not a problem. Even though I suggested how it could be fixed, I don’t think (and never considered) we should. The increased complexity and burden for users of volk is not worth it.
I agree that we should not require any of this. I just imagined a mechanism where a user may call init
and deinit
. If a user does not, the automatic route is preferred and I'd argue the automatic mechanism is the preferred one. Mostly because:
If this is really an issue – I doubt it is in any DSP heavy application – call any kernel once before starting main data processing.
The file is loaded only once. [...] Or don’t use unpredictable systems (GNU Radio wink) in the first place.
Are you sure? What about multi-threaded applications. Like GNU Radio. I only had a brief look, but I didn't find any locks.
There are no locks. https://github.com/gnuradio/volk/blob/cb87a41101fc0a754298919c610402512ea3299d/lib/volk_rank_archs.c#L55-L62
And the called function doesn't have one either
So far I haven't heard of any issues with this mechanism. And to conclude this:
Here, we call volk_rank_archs
.
If we provide a deinit
function, we should also spend some thought on how to make initialization thread safe. Unless, we decide that this is a user problem and VOLK does not make any guarantees to be thread safe. Though, I'd prefer to make sure initialization is thread-safe.
I assume a viable solution would rely on something with C atomic and C threads. This needs further investigation though.
Looks like preferences are loaded on the first access, but never destroyed. Can't find any helped method to properly cleanup.
Got this while running valgrind: