Feedback on MAJOR or MINOR version number increment #1371
vossmjp
started this conversation in
Design discussions
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
We are looking for advice on whether to increase the MINOR or MAJOR version number of oneTBB.
The oneTBB project uses semantic versioning (https://semver.org/) and as a oneAPI Library, the oneTBB project makes commitments around compatibility as described here. With semantic versioning, a MAJOR version increment generally means an incompatible API change, while a MINOR version increment means added functionality that is implemented in a backwards compatible manner. Since the migration from TBB to oneTBB, there have been over ten releases without a change to the MAJOR revision number, which is still 2021.
There are sometimes gray areas that require us to use our best judgement when deciding if we should increment the MAJOR or MINOR revision number. We currently have such as situation and are looking for opinions from the TBB user community.
Soon, we will introduce significant scalability enhancements to the
task_group
and flow graph APIs. The benefits can be large and will only be exposed when new oneTBB headers are used with a new oneTBB binary library. There are no source code changes required in applications. And while there will be additional DLL entry points, an application built against any previous 2021 version of oneTBB can be safely used with the new oneTBB binary library without recompilation.If your application does not use
task_group
or flow graph directly, these changes will not impact you. For example, there will be no issues if you only use oneTBB algorithms such asparallel_for
,parallel_reduce
, or the oneTBB scalable allocator, etc.However, we will be changing the layout of public classes for the
task_group
and flow graph APIs. These public classes will have the same public names between the versions but are implemented as aliases to internal classes that will have different names between the versions. Therefore, if some parts of the application that use these APIs have been compiled against an older 2021 version of oneTBB headers and some parts are compiled against these newer headers, wherever their source code files refer to these common public class name, those compilation units will now use different internal classes with different layouts and functions.If the whole application is recompiled against the new headers there is no issue; all components will use the same new internal classes and layouts. If a new binary library is dropped in and used with an application for which no component has been recompiled, there is no issue; all components will continue to use the old internal classes and layouts. An issue may only arise when there is a mixing of previously compiled code (against older 2021 headers) and newly compiled code (against the new headers), and in addition these incompatible objects are passed between the components, directly or indirectly. The components could be object files or shared libraries. Depending on the particular scenario, such mixing can result in link failures or even runtime failures (some examples are below).
We believe that this mixed compilation case with objects passed between components is a gray area. The most conservative solution is to increase the MAJOR revision number. However, this might come as an unnecessary nuisance for those interested only in the most common and fully supported backward compatibility scenarios, i.e., the drop-in replacement of the DLL with a previously compiled application or a complete application recompilation (with no need to change the source).
We’d like the community's opinion on what is the best choice in this situation.
The examples that follow demonstrate potential issues more concretely. For these examples, we will refer to the oneTBB version with the improvements as the improved oneTBB and any previous version as the current oneTBB.
The first example directly passes a
task_group
across the component boundary.In the preceding example, a
task_group
object is constructed inmain_direct.cpp
and passed torun_nested_task
defined indirect.cpp
. If both files are built, linked and then run with a single version of oneTBB there is no issue, whether it is the current or improved oneTBB. If both files are built and linked against a current oneTBB version and then run with the improved oneTBB version, there is also no issue. We believe these to be the most common usage scenarios.However, if one of these files is built against the current oneTBB and the other is built against the improved oneTBB, they will fail to link since
task_group
will be aliased to different internal symbols; the decorated symbol names forrun_nested_task
will not match. If both are built against the improved oneTBB and then run with a current oneTBB, the program will fail to resolve the new symbols at runtime.A more complicated scenario is when one of these affected objects is passed across the boundary indirectly, as shown below.
Now, a
task_group
object is constructed inmain_wrapped.cpp
and a wrapper object with a reference to thistask_group
is passed torun_nested_task
inwrapped.cpp
. As with the previous example, if both files are built, linked and then run with a single version of oneTBB there is no issue, whether it is the current or improved oneTBB. And similarly, if both files are built and linked against a current oneTBB version and then run with the improved oneTBB version, there is no issue.However, the mixed compilation cases become more problematic. If one of these files is built against the current oneTBB headers and the other is built against the improved oneTBB headers, they will fail to link against a current oneTBB library (since one of the files uses the new symbols) but will successfully link against the improved oneTBB library. The symbol names of
run_nested_task
in the two modules will match. Those object files or modules therefore successfully link, however the application will have undefined behavior at runtime: for example, it might crash or may even run to completion but with tasks dropped.So, what are your thoughts? Is the scenario with a mixed build and the passing of objects across boundaries a small corner case and so we should only increment the MINOR version number? Or should we conservatively increment the MAJOR version number?
We appreciate all feedback.
Beta Was this translation helpful? Give feedback.
All reactions