Closed Zaraka closed 10 months ago
You have compiled and installed kfr successfully but cannot link it to an external project, right?
Could you try to add this include before any other includes in the source file where you use kfr functions.
#include <kfr/config.h>
config.h
is generated as part of install process and should reside in your local/include directory.
Also please provide more information about your environment. OS and compiler used (with version). C++ flags and options (if not standard)
KFR 6 ( #196 ) will include prebuilt binaries ready for using with Windows, linux and macOS. This will also include Clang-compiled DFT for multiple architectures (selected at runtime).
I have tried including kfr/config.h as you requested. No changes. My config.h file contains only
#define KFR_DFT_NO_NPo2
Yes the installation succeded without any problems. Here is my CMakeCache.txt Installation is fine
/usr/local/lib$ ls
libkfr_dft.a libkfr_io.a
This is on Fedora 39, x86_64c++ (GCC) 13.2.1 20231011
This kfr copy is from current main 8d14765b988ba3d95476b5490d966ccaea7ae0c7
I'm linking with -lkfr_dft using QMake, but I also tried a test CMake project with
add_subdirectory(kfr)
target_link_libraries(apptestKFR
PRIVATE Qt6::Quick
kfr kfr_dft
)
same result. but I'm not that versed with CMake I maybe made a mistake somewhere. I'm not sure if is KFR even supported with GCC/MSVC. I can compile it with Clang if that is not the case, but I always thought linking Clang-compiled libraries with GCC/MSVC could get you unexpected results.
Just to test this out, I have tried also compiling KFR with Clang and then linking it with GCC, same result. I'll wait for KFR 6 and try again.
Linking GCC-compiled and Clang-compiled static libraries is perfectly fine as long as the both libraries have been built using the same C++ library (GCC's libstdc++ for Linux). The same applies for MSVC-compiled and Clang-compiled binaries (both should use Microsoft's STL). This is like Chrome/Chromium project is built by Google so it's battle-proven approach and shouldn't cause any issues.
As for linking ussue in KFR. There are two ways to use KFR. Use one architecture everywhere (but it must match in static library and your project) or use multiple architectures (selected at runtime).
Use -DKFR_ARCH=avx2 (or avx or sse41 or even sse2) when you run CMake to install KFR. Example:
cmake -GNinja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DKFR_ARCH=avx2 ..
ninja
sudo ninja install # This installs libkfr_dft.a
The same architecture should be used when building your source files: Example:
g++ -mavx2 ... your_source.cpp -lkfr_dft
Then linking works well and KFR will use avx2 instructions for both DFT and other functions (built in your code).
Code from examples/dft.cpp
will show:
KFR 5.1.0 avx2 64-bit (gcc-11.4.0/linux) +in
fft_specialization<double, 7>(avx2): 0, 128, 3072, 0, 1, 0, 0, 0, 1, 0, 0
First please update KFR using dev branch for small GCC compatibility fix.
Setting KFR_ENABLE_DFT_MULTIARCH
to ON
enables multiple architectures.
In this case instead of a single libkfr_dft.a
multiple arch-specific libraries will be installed.
cmake -GNinja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DKFR_ENABLE_DFT_MULTIARCH=ON ..
ninja
sudo ninja install # This installs libkfr_dft_sse2.a libkfr_dft_sse41.a libkfr_dft_avx.a libkfr_dft_avx2.a libkfr_dft_avx512.a
Then you can compile your code using any architecture settings but should link all KFR DFT libraries:
Example (gcc will select sse2 for your_source.cpp
):
g++ your_source.cpp -Wl,--push-state,--whole-archive -lkfr_dft_sse2 -Wl,--pop-state -lkfr_dft_sse41 -lkfr_dft_avx -lkfr_dft_avx2 -lkfr_dft_avx512
(Update: whole-archive flag is needed to link inline and template functions with correct architecture)
KFR code will detect cpu at runtime and select appropriate code path for DFT.
Code from examples/dft.cpp
will show:
KFR 5.1.0 sse2 64-bit (gcc-11.4.0/linux) +in
fft_specialization<double, 7>(avx2): 0, 128, 3072, 0, 1, 0, 0, 0, 1, 0, 0
Notice that first mentioned architecture is sse2 (architecture used for your_source.cpp
) while the second is now avx2 (dft source selected at runtime)
Hope this helps and let me know you have more questions.
@Zaraka DFT should be compiled using Clang anyway because the code that GCC generates for DFT is much slower. DFT performance comparison published for KFR was made using Clang and only with Clang we guarantee best performance. This won't affect your workflow because Clang should be used only for building static libraries. After building KFR libraries you are free to use any compiler and all should work ok. This applies for both KFR 5 and KFR 6.
The issue you mentioned could be easily fixed by specifying correct flags right now in KFR 5.
@Zaraka Is your problem resolved with the instructions above? If yes, I'll close the issue here.
@Zaraka Is your problem resolved with the instructions above? If yes, I'll close the issue here.
I'm sorry for the late answer I was very overburdened with other work. I have tested the latest commit from main/dev KFR 5.2.0, compiled with Clang as you requested with the linker flags you specified, linking succeeded. I will close this issue once I test it on the Windows platform as well, which should be today/tomorrow.
For Windows build instructions are similar but below are exact commands.
:: Warning: VS Path and LLVM Path may be different on your machine
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
cmake -GNinja -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe" -DCMAKE_LINKER="C:/Program Files/LLVM/bin/lld-link.exe" -DCMAKE_BUILD_TYPE=Release -DKFR_ARCH=avx2 -DCMAKE_INSTALL_PREFIX=install ..
ninja
ninja install # This installs kfr_dft.lib to CMAKE_BINARY_DIR/install
Then, the following compile options must be added (through VS Project Properties or CMake target_compile_options)
/arch:AVX2 "PATH-TO-INSTALLED-KFR/lib/kfr_dft.lib"
As always /arch
must match KFR_ARCH
argument in CMake call.
:: Warning: VS Path and LLVM Path may be different on your machine
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
cmake -GNinja -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe" -DCMAKE_LINKER="C:/Program Files/LLVM/bin/lld-link.exe" -DCMAKE_BUILD_TYPE=Release -DKFR_ENABLE_DFT_MULTIARCH=ON -DCMAKE_INSTALL_PREFIX=install ..
ninja
ninja install # This installs kfr_dft_sse2.lib kfr_dft_sse41.lib kfr_dft_avx.lib kfr_dft_avx2.lib kfr_dft_avx512.lib to CMAKE_BINARY_DIR/install
KFR_ENABLE_DFT_MULTIARCH=ON
is the key option here.
/WHOLEARCHIVE:"PATH-TO-INSTALLED-KFR/lib/kfr_dft_sse2.lib" "PATH-TO-INSTALLED-KFR/lib/kfr_dft_sse41.lib" "PATH-TO-INSTALLED-KFR/lib/kfr_dft_avx.lib" "PATH-TO-INSTALLED-KFR/lib/kfr_dft_avx2.lib" "PATH-TO-INSTALLED-KFR/lib/kfr_dft_avx512.lib"
/WHOLEARCHIVE
for sse2 lib is required here for the same reason as linux code has --whole-archive
: to force compiler to select correct inline/template functions from multiple similar libraries. Without this a runtime invalid instruction exception may occur.
I followed the instructions as requested and got everything in working order. Thank you very much for your help, I would strongly suggest writing this kind of information into ReadMe.md or Installation.md as I was previously unable to find this exact information anywhere in Documentation.
While evaluating this library I ran into an odd issue. I have compiled the kfr library with DFT, tests, and examples enabled. All Tests and examples work great. I then proceed to install the kfr library as normal, resulting in kfr_dft.a and kfr_io.a in my local/lib folder.
But If I try to copy/paste dft example into my separate qmake/cmake project and then linking the library as normal like this
It does not compile and crash on the error
While digging in the fft.htpp I noticed KFR_DFT_MULTI macro which was not defined anywhere. So I just try to define it before including
and the binary started successfully linking against kfr_dft but dft example still does not work, because dft_plan is not properly initialized and it crashes on execute. Backtrace here
I seriously do not understand whether I compiled or installed kfr incorrectly. Would appreciate any help