Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix compile against lapack-3.10.0 - part 1 #21114

Merged
merged 2 commits into from Dec 22, 2021
Merged

Fix compile against lapack-3.10.0 - part 1 #21114

merged 2 commits into from Dec 22, 2021

Conversation

dwardor
Copy link
Contributor

@dwardor dwardor commented Nov 24, 2021

TODO:

  • alalek: update builders configuration (to resolve Mac builder report) if it is not caused by CONFIG usage in find_package removed CONFIG
  • alalek: validate MKL integration

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
  • The PR is proposed to proper branch
  • There is reference to original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

@dwardor
Copy link
Contributor Author

dwardor commented Nov 24, 2021

Fixes #21116

@alalek
Copy link
Member

alalek commented Nov 24, 2021

This change breaks Linux builds - LAPACK becomes disabled.

@msva
Copy link

msva commented Dec 2, 2021

This change breaks Linux builds - LAPACK becomes disabled.

actually, it fixes linux builds. On systems with modern versions of lapack.

@devurandom
Copy link

This change breaks Linux builds - LAPACK becomes disabled.

actually, it fixes linux builds. On systems with modern versions of lapack.

I assume for this to be accepted it has to work with both old and modern versions of LAPACK?

Could this be done by checking for both sposv_ (e.g.) and LAPACK_sposv_ and setting a -D preprocessor definition and then in the code using:

#ifdef OPENCV_USE_OLD_LAPACK
#  define LAPACK_sposv_ sposv_
#endif

?

@devurandom
Copy link

This fixes #19846 (of which #21116 is a duplicate).

@msva
Copy link

msva commented Dec 2, 2021

@dwardor could you please add checks (to stay compatible with older lapack versions)?

And also merge another PR (the part2) here, as, actually, it seems to be related to the same exact issue, so no need to split it to another PR, IMO.

@vpisarev vpisarev self-assigned this Dec 3, 2021
@vpisarev
Copy link
Contributor

vpisarev commented Dec 3, 2021

@dwardor, thank you for the patch!

I'm sure, it's useful, but I think we need to do it in a proper way:

  1. the version of Lapack needs to be detected somewhere in CMake or maybe using some #ifdef's inside the code.
  2. all the calls to Lapack needs to be wrapped into a macro, e.g.
#ifdef OPENCV_USE_LAPACK_PREFIX
#define LAPACK_FUNC(f) LAPACK_##f
#else
#define LAPACK_FUNC(f) f
#endif
...

then you should define or not OPENCV_USE_LAPACK_PREFIX, depending on the version.

@dwardor
Copy link
Contributor Author

dwardor commented Dec 4, 2021

Just pushed a new version that should be more generic per vpisarev's recommendations

  • defines the new configuration parameter OPENCV_USE_LAPACK_PREFIX set to OFF by default so as to change nothing
  • uses this configuration parameter to #define LAPACK_FUNC(f)

This still works on gentoo with lapack 3.10.0 by configuring OPENCV_USE_LAPACK_PREFIX=ON via ebuild
If someone can test on lapack < 3.9.1 and confirm it still works too...

Tried but failed to figure out how to test lapack version in OpenCVFindLAPACK.cmake (am a cmake noob).
If anyone has a hint to spare...

CMakeLists.txt Outdated
@@ -527,6 +527,8 @@ OCV_OPTION(OPENCV_SEMIHOSTING "Build the library for semihosting target
OCV_OPTION(ENABLE_PYLINT "Add target with Pylint checks" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )
OCV_OPTION(ENABLE_FLAKE8 "Add target with Python flake8 checker" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )

OCV_OPTION(OPENCV_USE_LAPACK_PREFIX "Use LAPACK_ prefix for function calls with lapack >= 3.9.1." OFF)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about setting it to "ON" based on detected lapack version (to ease downstream maintenance work)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds great to me! Just haven't figured out how to do it

@dwardor
Copy link
Contributor Author

dwardor commented Dec 5, 2021

This autodetects LAPACK_VERSION, at least on my gentoo box, and activates OPENCV_USE_LAPACK_PREFIX automatically... I've only used LAPACK_FUNC to the function that strictly need it...

My gut feeling is :

  • That (at least for lapack > 3.7.0) all lapack function calls should be using LAPACK_xxxx (whatever the lapack version) as those are the base functions names that are then converted by the preprocessor to xxxx_ or xxxx or XXXX_ or XXXX depending on platform/architecture via the macros in lapack.h and lapacke_mangling.h (and sometimes since lapack 3.9.1 the preprocessors also add an extra parameter depending on the platform/architecture/compiler. Right now opencv presumes the xxxx_ variant is the correct one for all and does not let the preprocessor do the work it is supposed to do (which causes the issues for the extra parameters with lapack >= 3.9.1)

  • Depending on lowest lapack version compiled agains, we could probably remove LAPACK_FUNC and OPENCV_USE_LAPACK_PREFIX totaly by converting all xxxx_ to LAPACK_xxxx in hal_internal.cpp

@dwardor
Copy link
Contributor Author

dwardor commented Dec 5, 2021

Been looking through all lapack-release versions... and c/c++ interfaces appeared back in 3.4.0 :
lapack.h's content was at the time inside lapacke.h
LAPACK_xxxx was still the default function name + preprocessor macros (not exactly the same) were also present...

#ifndef LAPACK_NAME
#define LAPACK_NAME(lcname,UCNAME)  lcname##_
#endif
...
#define LAPACK_sposv LAPACK_NAME(sposv,SPOSV)
...
void LAPACK_sposv( char* uplo, lapack_int* n, lapack_int* nrhs, float* a,
                   lapack_int* lda, float* b, lapack_int* ldb,
                   lapack_int *info );

So just using LAPACK_xxxx in opencv source and letting the preprocessor macros do their job is the universal solution for anything above lapack-3.4.0.

Am I right in saying no one is compiling opencv vs. anything <3.4.0 as it contains no c/c++ interface ?

LAPACK_NAME(lcname,UCNAME) was replaced by LAPACK_GLOBAL(lcname,UCNAME) in lapack-3.4.1

Copy link
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for update!

Please take a look on comments below.

@@ -156,8 +163,16 @@ if(WITH_LAPACK)
if(WIN32 AND NOT OPENCV_LAPACK_SHARED_LIBS)
set(BLA_STATIC 1)
endif()
find_package(LAPACK)
find_package(LAPACK CONFIG)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONFIG

Why do we need to block CMake's LAPACK module?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just use CONFIG so as to have access to LAPACK_VERSION. If I don't add CONFIG LAPACK_VERSION is undefined.

#ifdef OPENCV_USE_LAPACK_PREFIX
#define LAPACK_FUNC(f) LAPACK_##f
#else
#define LAPACK_FUNC(f) f##_
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LAPACK_FUNC

Please use OPENCV_ / OCV_ prefix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

@@ -51,6 +51,13 @@ macro(ocv_lapack_check)
if(NOT "${OPENCV_CBLAS_H_PATH_${_lapack_impl}}" STREQUAL "${OPENCV_LAPACKE_H_PATH_${_lapack_impl}}")
list(APPEND _lapack_content "#include \"${OPENCV_LAPACKE_H_PATH_${_lapack_impl}}\"")
endif()
list(APPEND _lapack_content "
#ifdef OPENCV_USE_LAPACK_PREFIX
#define LAPACK_FUNC(f) LAPACK_##f
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-DOPENCV_USE_LAPACK_PREFIX=LAPACK_

It makes sense to define prefix in CMake.


Moreover, we don't need global compiler definition at all.
It is a generated file. So generate this content through CMake conditions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok will remove the global alltogether and generate based in CMake conditions

@dwardor
Copy link
Contributor Author

dwardor commented Dec 20, 2021

I'd prefer we use #21291 instead of this as per #21114 (comment)

Update : #21291 is dead due to imcompatibility with Accelerate LAPACK implementation so this pullrequest seems the way to move forward

@dwardor
Copy link
Contributor Author

dwardor commented Dec 21, 2021

Only issue seems to be Mac build (just a warning ?)... @alalek I don't know how to debug this as I don't have a Mac...

Fix compilation against lapack >= 3.9.1 and 3.10.0 while not breaking older versions

OpenCVFindLAPACK.cmake & CMakeLists.txt: determine OPENCV_USE_LAPACK_PREFIX from LAPACK_VERSION

hal_internal.cpp : Only apply LAPACK_FUNC to functions whose number of inputs depends on LAPACK_FORTRAN_STR_LEN in lapack >= 3.9.1

lapack_check.cpp : remove LAPACK_FUNC which is not OK as function are not used with input parameters (so lapack.h preprocessing of "LAPACK_xxxx(...)" is not applicable with lapack >= 3.9.1
If not removed lapack_check fails so LAPACK is deactivated in build (not want we want)

use OCV_ prefix and don't use Global, instead generate OCV_LAPACK_FUNC depending on CMake Conditions

Remove CONFIG from find_package(LAPACK) and use LAPACK_GLOBAL and LAPACK_NAME to figure out if using netlib's reference LAPACK implementation and how to #define OCV_LAPACK_FUNC(f)
Copy link
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done!

@dwardor Thank you for the patch!

@msva @devurandom Thank you for the review proposals!

@alalek alalek merged commit 54c1800 into opencv:3.4 Dec 22, 2021
@dwardor
Copy link
Contributor Author

dwardor commented Dec 22, 2021

Thanks for the various pointers on the way.

@alalek will this also make it into opencv:4.x ?

@alalek
Copy link
Member

alalek commented Dec 22, 2021

Changes to 4.x will be propagated automatically during the next "Merge-3.4" PR: https://github.com/opencv/opencv/wiki/Branches

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants