Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Vino
Aug 11, 2010
Thanks Plorkyeran! Indeed I didn't know about some of that stuff.

Xarn posted:

The latter is you being bad at cmake, per project flags are easy and old.

You absolutely do not want per-file flags. I mean it. Don't. (Honestly you don't really want per project flags that are ABI-changing either, but eh)

Yes I agree, I certainly won't claim (or aspire) to be good at CMake. You're probably right about per-file flags, but I definitely wanted per-executable flags. The source of this was I have some tests (separate executables) and I don't remember which switch I wanted to compile with some of them different and after a while of google searching and documentation reading I couldn't figure out how to do so.

Adbot
ADBOT LOVES YOU

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.
Does anyone have any favorite books / references / articles / blog posts about static vs dynamic linking? I'm trying to wrap my head around a good plan for an HPC cluster that I inherited without much guidance.

The most common options in the HPC space seem to be either statically linking everything, or putting a network share on LD_LIBRARY_PATH and putting all of the .sos that binaries need there. I didn't know about these approaches and have just been merrily installing all of the library dependencies across the cluster with Ansible, but I think it's time to fall more in line with norms.

More broadly on the topic of static vs dynamic linking, I found this approach pretty pragmatic, to dynamically link, but ship all of your dependencies other than libc with your binary.

Am I overthinking this and just static linking everything is the way to go for portable binaries of software that's built outside of a system's repository infrastructure?

Some relevant thoughts about why static linking is king for scientific computing: https://ro-che.info/articles/2016-09-09-static-binaries-scientific-computing

Twerk from Home fucked around with this message at 04:14 on Sep 29, 2021

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Dynamic linking typically makes linking faster, which can be great for debug builds. For release builds where you're shipping all the libraries yourself, not sharing them with anything, and don't care to support people replacing your copy of library with a different one, there isn't much of a reason to dynamically link.

Xarn
Jun 26, 2015
static link everything you have sources for and isn't limited by license (e.g. ffmpeg with lgpl).

Xarn
Jun 26, 2015

Vino posted:

Thanks Plorkyeran! Indeed I didn't know about some of that stuff.

Yes I agree, I certainly won't claim (or aspire) to be good at CMake. You're probably right about per-file flags, but I definitely wanted per-executable flags. The source of this was I have some tests (separate executables) and I don't remember which switch I wanted to compile with some of them different and after a while of google searching and documentation reading I couldn't figure out how to do so.

It is target_compile_options, which as far as I can tell was introduced in 3.0, aka before I even started programming. :v:

But yeah, CMake documentation is amazingly unopinionated and does bad job steering you towards doing the right thing. Basically you have to look for tutorials/guides for "Modern CMake", and even then you run into tutorials for like 3.10, with workaround for things you can do straightforwardly in current versions. But at least "Modern CMake" steers you towards doing things through targets, which is the basic requirement not to go insane.

Foxfire_ posted:

"Use different warnings settings on these files" isn't an unreasonable ask

warning flags are one of the few things that won't break things if they are inconsistent, but it already seems sketchy tbh. I would rather you have the same set of warning flags in a project, and disable the ones you don't care for locally than trying to pick apart a build script to see which warnings apply to which files.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Plorkyeran posted:

Dynamic linking typically makes linking faster, which can be great for debug builds. For release builds where you're shipping all the libraries yourself, not sharing them with anything, and don't care to support people replacing your copy of library with a different one, there isn't much of a reason to dynamically link.
The other use for dynamic linking is optional plugins, which are a bit different because you have to do *real* dynamic linking where the program itself does the final linking, rather than the linker generating all the connections and auto-connecting them at init time.

matti
Mar 31, 2019

learning the win32 api at long last (just to fix a bug in a software I want to use lol)

i think everyone first project is to write a function to report system library errors, here is mine.

which brings me to ask, how you do test for signed integer overflow when you use Microsoft's compiler? is there anything similar to GNU's __builtin_<op>_overflow() functions? or are you just supposed to make assumptions about widths of types and write your own in which you cast to the size next larger to test the result?

csammis
Aug 26, 2003

Mental Institution

Xarn posted:

warning flags are one of the few things that won't break things if they are inconsistent, but it already seems sketchy tbh. I would rather you have the same set of warning flags in a project, and disable the ones you don't care for locally than trying to pick apart a build script to see which warnings apply to which files.

External code (third party libraries, headers supplied by vendors) are an excellent use case for setting different warning levels in the build pipeline and not modifying the code to set #pragmas or whatever, since you probably shouldn’t be or can’t be making local modifications to code that isn’t yours.

Even then though best practice would have you keeping all external code in a separate directory for which you could set the warnings rather than per file.

Vino
Aug 11, 2010

Xarn posted:

It is target_compile_options, which as far as I can tell was introduced in 3.0, aka before I even started programming. :v:

Thank you! I'll give it a try next time I run in to this.

Xarn
Jun 26, 2015

csammis posted:

External code (third party libraries, headers supplied by vendors) are an excellent use case for setting different warning levels in the build pipeline and not modifying the code to set #pragmas or whatever, since you probably shouldn’t be or can’t be making local modifications to code that isn’t yours.

That's why you pragma it away in your own code, or create wrapper over it.

But really, if the problem is third party headers dragging in warnings into your own TUs, the chances are that what you want is -isystem, because afaik even MSVC bumbled their way into useful implementation of it, because that is simpler than ensuring that all your TUs that touch said header disable specific warnings.

nielsm
Jun 1, 2009



matti posted:

learning the win32 api at long last (just to fix a bug in a software I want to use lol)

i think everyone first project is to write a function to report system library errors, here is mine.

which brings me to ask, how you do test for signed integer overflow when you use Microsoft's compiler? is there anything similar to GNU's __builtin_<op>_overflow() functions? or are you just supposed to make assumptions about widths of types and write your own in which you cast to the size next larger to test the result?

On Win32 (including 64 bit) the int type is always 32 bit wide.
As far as I can tell, Microsoft's compiler does not have a way to detect integer overflow after the fact. Write your code so it doesn't cause overflow in the first place. (Or assume nobody's going to supply a message and format input exceeding 2 GB.)

Write a function or two to do saturating addition if you really want to attempt to handle those absurd cases. At least x86 and x86_64 offer saturating arithmetic intrinsics.
Personally I think it'd be better to just limit the buffers to something reasonable like 64k.

Edit: I guess you can use the _addcarry_u32 function on x86/64 to do addition and check for nonzero carry to detect overflow.

quote:

code:
// Are the messages for error codes ever localized?
Yes.
And it looks really dumb when a program in one language prints an error message in a different language, that it fetched from the OS. You should definitely try to request the message in the UI language your program is using rather than the user default UI language for the system. But if the requested language isn't on the system it should be falling back to one that does exist.

nielsm fucked around with this message at 22:11 on Sep 29, 2021

matti
Mar 31, 2019

i will take that as MSVC will not re-order my overflow checks.

nielsm posted:

(Or assume nobody's going to supply a message and format input exceeding 2 GB.)

hmmmm

matti fucked around with this message at 22:21 on Sep 29, 2021

Foxfire_
Nov 8, 2010

Xarn posted:

That's why you pragma it away in your own code, or create wrapper over it.

But really, if the problem is third party headers dragging in warnings into your own TUs, the chances are that what you want is -isystem, because afaik even MSVC bumbled their way into useful implementation of it, because that is simpler than ensuring that all your TUs that touch said header disable specific warnings.
The actual situation where I've wanted it is a TU with a bunch of googletest's test fixture macros (which triggers the warnings) where I am #including my header-only code-under-test where I want the warnings on. Mostly just an annoying collision of a bunch of macros and templates.

matti posted:

i will take that as MSVC will not re-order my overflow checks.
You may not standards compliantly check for signed overflow after the fact in C/C++ using normal arithmatic, the compiler is allowed to apply transformations under the assumption that overflow never happens

intsafe.h is the MSVC equivalent of the gcc __builting_*overflow() functions [though looking at their implementations, they're undefined behavior/using secret knowledge about how the optimizer works and just doing the same overflow checks you would do]

matti
Mar 31, 2019

Foxfire_ posted:

intsafe.h is the MSVC equivalent of the gcc __builting_*overflow() functions [though looking at their implementations, they're undefined behavior/using secret knowledge about how the optimizer works and just doing the same overflow checks you would do]

thanks this is the knowledge i was looking for xoxo

matti
Mar 31, 2019

i ended up on the solution where i just write trivial inline assembly routines for signed integer addition when i have to do it

functions have the signature <op>_<types> or <op>_<type>_<to|by>_<type> and take a jmp_buf as a third argument for handling overflow.

only downside is having to declare pointers as volatile if you want to free them in the clean-up code. but it keeps any arithmetic very readable.

'unno, this is for personal stuff, i would not do this in an organization

matti fucked around with this message at 17:24 on Sep 30, 2021

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
If this is for personal stuff, have you considered just using clang? It’s literally supported by Microsoft now.

matti
Mar 31, 2019

too new, maybe in couple of years

i do not typically expect anything to work

matti fucked around with this message at 05:54 on Oct 1, 2021

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.
I'm back with more CMAKE troubles.

I'm trying to statically link an application that's using BLAS/LAPACK with a CMAKE build. I am intending to have this support both OpenBLAS an Intel MKL. Cmake is finding my libraries just fine with FindBLAS, like this:

code:
-- Found BLAS: /usr/lib/x86_64-linux-gnu/libmkl_intel_lp64.a;/usr/lib/x86_64-linux-gnu/libmkl_sequential.a;/usr/lib/x86_64-linux-gnu/libmkl_core.a;-lpthread;-lm;-ldl  
However, because finding BLAS is sticking -lpthread;-lm;-ldl on the end of the BLAS library string, when it comes time to link, CMake is marking those dynamic. The link.txt that CMake is generating that is what the linker is called with ends up looking like this, while what I am wanting is an entirely static link:

code:
-static -Wl,--start-group -Wl,-Bstatic -lmkl_intel_lp64 -lmkl_sequential -lmkl_core \
-Wl,-Bdynamic -lpthread -lm -ldl -Wl,-Bstatic -lmkl_intel_lp64 -lmkl_sequential -lmkl_core \
-Wl,-Bdynamic -lpthread -lm -ldl -Wl,--end-group \
-larmadillo /usr/lib/x86_64-linux-gnu/libboost_iostreams.a -Wl,-Bstatic -lz -lpthread -lgfortran -lquadmath -Wl,-Bdynamic
I need some way to get CMake to stop stuffing -Bdynamic and -Bstatic all over the place and just let -static do its work. I hacked through this to actually get, validate, and profile a static executable by editing CMake's generated link.txt file and replacing every -Bdynamic with -Bstatic, and it accomplished what I wanted. The best solution would be if CMake wouldn't put those there in the first place. Ideas?

Edit:

I worked around this by doing an incredibly un-Cmake thing and manually passing it the linker flags I want it to use, so now my build is incredibly un-portable and Intel MKL only to build a static build. I think that I really want two completely different CMakeLists.txt , one that is able to build on most machines letting Cmake find the libraries, and using the libraries it finds to build & link a dynamically linked executable, and another entirely separate build process that is extremely tightly coupled to Ubuntu 20.04 with Intel MKL, but produces a static executable that will run everywhere. Thoughts about that approach?

Twerk from Home fucked around with this message at 23:01 on Oct 1, 2021

Volguus
Mar 3, 2009
I have a question about boost::shared_mutex and boost::shared_lock. I have this class:

C++ code:
class Foo
{
public:
  int GetValueDouble() const
  {
    boost::shared_lock<boost::shared_mutex> lock(mutex);
    return GetValue() * 2;
  }
  int GetValue() const
  {
    boost::shared_lock<boost::shared_mutex> lock(mutex);
    return value;
  }
private:
    mutable boost::shared_mutex mutex;
    int value = 1;
};

Now, just running this code by itself in a "hello world" program, works just fine. But, in a more complex program, with 40+ threads that makes quite heavy use of these shared_lock and unique_lock I can sometimes see deadlocks happening. Hard to debug as hell (as in I cannot figure out who the hell has the exclusive lock to the mutex, looking in every thread, every frame, they're all seem to just be waiting for an exclusive lock to become free). To me this looks fishy, but I was not able to find anything online that would tell me straight up "don't do this".

Is it ... ok? I'd say it isn't.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I don’t see anything in the documentation that says that boost::shared_mutex supports recursive locking, no. It’s just a reader/writer lock.

Volguus
Mar 3, 2009

rjmccall posted:

I don’t see anything in the documentation that says that boost::shared_mutex supports recursive locking, no. It’s just a reader/writer lock.

That's exactly it. Nobody said "this is cool" and nobody said "don't do it". I'm just hunting for 2 days for that writer lock and I can't find it. That someone, that must be there that must hold the exclusive lock and I just can't find it. Everyone is saying they're waiting to get the lock (attaching with gdb to the deadlocked program) but nobody seems to own the drat lock. For now, I just changed the code to just return value*2 and so far so good. I'm just ... dunno, throwing my hands up in the air.

Or, are you saying that if they don't specify that they support recursive locking therefore implicitly it's not cool at all?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Volguus posted:

That's exactly it. Nobody said "this is cool" and nobody said "don't do it". I'm just hunting for 2 days for that writer lock and I can't find it. That someone, that must be there that must hold the exclusive lock and I just can't find it. Everyone is saying they're waiting to get the lock (attaching with gdb to the deadlocked program) but nobody seems to own the drat lock. For now, I just changed the code to just return value*2 and so far so good. I'm just ... dunno, throwing my hands up in the air.
I think the problem with the recursive locking is not that recursive locking itself is a problem, but rather that once someone gets an upgrade_lock that they're planning on turning into a unique_lock (or just gets a unique_lock) further attempts to get a readlock will block, while that write lock waits for all the readers to release.

So if you recurse the readlock like you do in that example, you potentially run into a case where you go ...

code:
  thread 1: readlock
  thread 2: startwritelock
  thread 1: attempt the inner readlock, blocked because a writelock is waiting to get a turn
  thread 2: still waiting for thread 1's readlock to release
  thread 1: still blocked
... which is why nobody owns the lock, because the writelock didn't get it yet, but the fact that it's trying to prevents readlocks.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Volguus posted:

Or, are you saying that if they don't specify that they support recursive locking therefore implicitly it's not cool at all?

This, yes. You should not assume a mutex supports recursive locking unless it says it does.

Separately, yes, if everything acquiring a reader/writer lock is acquiring it in reader mode then the lock isn’t doing anything useful.

EpicCodeMonkey
Feb 19, 2011

Twerk from Home posted:

I'm back with more CMAKE troubles.

I'm trying to statically link an application that's using BLAS/LAPACK with a CMAKE build. I am intending to have this support both OpenBLAS an Intel MKL. Cmake is finding my libraries just fine with FindBLAS, like this:

code:
-- Found BLAS: /usr/lib/x86_64-linux-gnu/libmkl_intel_lp64.a;/usr/lib/x86_64-linux-gnu/libmkl_sequential.a;/usr/lib/x86_64-linux-gnu/libmkl_core.a;-lpthread;-lm;-ldl  
However, because finding BLAS is sticking -lpthread;-lm;-ldl on the end of the BLAS library string, when it comes time to link, CMake is marking those dynamic. The link.txt that CMake is generating that is what the linker is called with ends up looking like this, while what I am wanting is an entirely static link:

code:
-static -Wl,--start-group -Wl,-Bstatic -lmkl_intel_lp64 -lmkl_sequential -lmkl_core \
-Wl,-Bdynamic -lpthread -lm -ldl -Wl,-Bstatic -lmkl_intel_lp64 -lmkl_sequential -lmkl_core \
-Wl,-Bdynamic -lpthread -lm -ldl -Wl,--end-group \
-larmadillo /usr/lib/x86_64-linux-gnu/libboost_iostreams.a -Wl,-Bstatic -lz -lpthread -lgfortran -lquadmath -Wl,-Bdynamic
I need some way to get CMake to stop stuffing -Bdynamic and -Bstatic all over the place and just let -static do its work. I hacked through this to actually get, validate, and profile a static executable by editing CMake's generated link.txt file and replacing every -Bdynamic with -Bstatic, and it accomplished what I wanted. The best solution would be if CMake wouldn't put those there in the first place. Ideas?

Edit:

I worked around this by doing an incredibly un-Cmake thing and manually passing it the linker flags I want it to use, so now my build is incredibly un-portable and Intel MKL only to build a static build. I think that I really want two completely different CMakeLists.txt , one that is able to build on most machines letting Cmake find the libraries, and using the libraries it finds to build & link a dynamically linked executable, and another entirely separate build process that is extremely tightly coupled to Ubuntu 20.04 with Intel MKL, but produces a static executable that will run everywhere. Thoughts about that approach?

The FindBLAS documentation says that it exports BLAS_LIBRARIES and BLAS_LINKER_FLAGS variables in addition to the BLAS::BLAS alias target, the latter of which excludes all the -l and -L dynamic libraries. Perhaps try to link against those rather than use the exported target?

Volguus
Mar 3, 2009
Thank you so much. This all became so much clearer now. It's definitely what's going on, as roomforthetuna stated, the unique_locks that are happening are just waiting for the readlocks to return which they never do since that write lock is ... locking. I never used the shared/unique locks of boost since I never really understood them. It seems that the original writers of this code (there are a bunch, over many years, so it all makes sense) didn't either. Yes, removing the recursive locks should be first priority for now.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
Are the boost synchronization primitives compatible with clang thread safety annotations like GUARDED_BY, LOCKS_EXCLUDED, etc.? Those things are great for preventing you from accidentally trying to double-lock.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
Related question, are shared locks significantly more expensive than just doing regular exclusive locks? I mean obviously they're better for the cases where they're clearly appropriate, but if e.g. you just have two threads, one reading and one writing, is using shared_lock for the reader and unique_lock for the writer going to be a meaningful performance-suck compared to if you just used std::scoped_lock for both, or is it basically irrelevant such that using a read-write lock is worth it just in case occasionally you spin up a third thread and two reads sometimes want to happen at the same time?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Yeah, even if shared acquire/release happen to work under recursion, it’s quite likely that upgrades don’t and will deadlock if performed recursively while holding a shared lock. That would be a natural result of an implementation that e.g. just kept a reader count.

Regardless, of course, you shouldn’t rely on a property that isn’t promised by the documentation.

Winter Stormer
Oct 17, 2012

Twerk from Home posted:

Edit:

I worked around this by doing an incredibly un-Cmake thing and manually passing it the linker flags I want it to use, so now my build is incredibly un-portable and Intel MKL only to build a static build. I think that I really want two completely different CMakeLists.txt , one that is able to build on most machines letting Cmake find the libraries, and using the libraries it finds to build & link a dynamically linked executable, and another entirely separate build process that is extremely tightly coupled to Ubuntu 20.04 with Intel MKL, but produces a static executable that will run everywhere. Thoughts about that approach?

Sucks, but you do what you gotta do sometimes.

For what it's worth, I tried to recreate your problem on Fedora and failed.

pre:
[khulud@phoenix build]$ cat ../CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(test)

add_executable(exe main.cpp)
set(CMAKE_EXE_LINKER_FLAGS -static)

set(BLA_STATIC on)
find_package(BLAS)

target_link_libraries(exe PRIVATE BLAS::BLAS)
[khulud@phoenix build]$ cmake --version
cmake version 3.20.5

CMake suite maintained and supported by Kitware (kitware.com/cmake).
[khulud@phoenix build]$ cmake -G Ninja ..
[...]
-- Found BLAS: -Wl,--start-group;/opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_intel_lp64.a;/opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_sequential.a;/opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_core.a;-Wl,--end-group;-lpthread;-lm;-ldl  
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/wow/build
[khulud@phoenix build]$ ninja
[2/2] Linking CXX executable exe
[khulud@phoenix build]$ ninja -t commands
/usr/bin/c++    -MD -MT CMakeFiles/exe.dir/main.cpp.o -MF CMakeFiles/exe.dir/main.cpp.o.d -o CMakeFiles/exe.dir/main.cpp.o -c ../main.cpp
: && /usr/bin/c++  -static CMakeFiles/exe.dir/main.cpp.o -o exe  -Wl,--start-group  /opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_intel_lp64.a  /opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_sequential.a  /opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_core.a  -Wl,--end-group  -lpthread  -lm  -ldl && :
[khulud@phoenix build]$ file exe 
exe: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=2f2cf350d5012a37de7b552295e438dd0d334552, for GNU/Linux 3.2.0, not stripped, too many notes (256)
[khulud@phoenix build]$ ./exe
Major version:           2021
Minor version:           0
Update version:          4
Product status:          Product
Build:                   20210904
Platform:                Intel(R) 64 architecture
Processor optimization:  Intel(R) Advanced Vector Extensions 2 (Intel(R) AVX2) enabled processors
================================================================

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

roomforthetuna posted:

Related question, are shared locks significantly more expensive than just doing regular exclusive locks?

In principle, no, they should be doing roughly the same atomic operations in roughly the same sequence as would be require for an exclusive lock, and the only cost difference is that reader-writer locks avoid blocking threads in more situations.

In practice, reader-writer locks tend to be substantially less tuned; it’s not uncommon for a reader-writer lock to be implemented with something like a mutex and a condition variable behind the scenes, which will be much less efficient. Also, while I’ve heard legends of reader-writer locks with priority inversion avoidance, I don’t know of any platforms that actually do it.

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.

Winter Stormer posted:

Sucks, but you do what you gotta do sometimes.

For what it's worth, I tried to recreate your problem on Fedora and failed.

pre:
[khulud@phoenix build]$ cat ../CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(test)

add_executable(exe main.cpp)
set(CMAKE_EXE_LINKER_FLAGS -static)

set(BLA_STATIC on)
find_package(BLAS)

target_link_libraries(exe PRIVATE BLAS::BLAS)
[khulud@phoenix build]$ cmake --version
cmake version 3.20.5

CMake suite maintained and supported by Kitware (kitware.com/cmake).
[khulud@phoenix build]$ cmake -G Ninja ..
[...]
-- Found BLAS: -Wl,--start-group;/opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_intel_lp64.a;/opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_sequential.a;/opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_core.a;-Wl,--end-group;-lpthread;-lm;-ldl  
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/wow/build
[khulud@phoenix build]$ ninja
[2/2] Linking CXX executable exe
[khulud@phoenix build]$ ninja -t commands
/usr/bin/c++    -MD -MT CMakeFiles/exe.dir/main.cpp.o -MF CMakeFiles/exe.dir/main.cpp.o.d -o CMakeFiles/exe.dir/main.cpp.o -c ../main.cpp
: && /usr/bin/c++  -static CMakeFiles/exe.dir/main.cpp.o -o exe  -Wl,--start-group  /opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_intel_lp64.a  /opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_sequential.a  /opt/intel/oneapi/mkl/2021.4.0/lib/intel64/libmkl_core.a  -Wl,--end-group  -lpthread  -lm  -ldl && :
[khulud@phoenix build]$ file exe 
exe: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=2f2cf350d5012a37de7b552295e438dd0d334552, for GNU/Linux 3.2.0, not stripped, too many notes (256)
[khulud@phoenix build]$ ./exe
Major version:           2021
Minor version:           0
Update version:          4
Product status:          Product
Build:                   20210904
Platform:                Intel(R) 64 architecture
Processor optimization:  Intel(R) Advanced Vector Extensions 2 (Intel(R) AVX2) enabled processors
================================================================

I really appreciate this! I was going to post a minimal example to pull this out from all the other libraries I'm linking hoping to get some help like this, but you went and did it for me. I'm going to fix up my CMakeLists and probably be in business. I'm a CMake novice muddling through, and what I had was more like:

pre:
cmake_minimum_required(VERSION 3.0)
project(main)

set(CMAKE_CXX_STANDARD 17)

set(BLA_STATIC ON)
find_package(LAPACK REQUIRED)
find_package(BLAS REQUIRED)

... other libs and all project support files

target_link_libraries(main -static)
target_link_libraries(main ${BLAS_LIBRARIES})

Winter Stormer
Oct 17, 2012

Twerk from Home posted:

I really appreciate this! I was going to post a minimal example to pull this out from all the other libraries I'm linking hoping to get some help like this, but you went and did it for me. I'm going to fix up my CMakeLists and probably be in business. I'm a CMake novice muddling through, and what I had was more like:

pre:
cmake_minimum_required(VERSION 3.0)
project(main)

set(CMAKE_CXX_STANDARD 17)

set(BLA_STATIC ON)
find_package(LAPACK REQUIRED)
find_package(BLAS REQUIRED)

... other libs and all project support files

target_link_libraries(main -static)
target_link_libraries(main ${BLAS_LIBRARIES})

I futzed with it a little further just now and did manage to break my build by setting cmake_version_required < version 3.3. Since that function sets CMake policy versions, I went looking at what policies 3.3 added, and I'm pretty certain you're running into the problem fixed by https://cmake.org/cmake/help/latest/policy/CMP0060.html. Try setting your minimum to be 3.3 or better.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

rjmccall posted:

In principle, no, they should be doing roughly the same atomic operations in roughly the same sequence as would be require for an exclusive lock, and the only cost difference is that reader-writer locks avoid blocking threads in more situations.

In practice, reader-writer locks tend to be substantially less tuned; it’s not uncommon for a reader-writer lock to be implemented with something like a mutex and a condition variable behind the scenes, which will be much less efficient. Also, while I’ve heard legends of reader-writer locks with priority inversion avoidance, I don’t know of any platforms that actually do it.
Cool, thanks! So theoretically you should use reader-writer locks, but in reality you should just use exclusive locks unless you're pretty sure you have a good reason to go readwrite, because the cognitive overhead of the more complicated lock and the probable implementation quality difference are likely bigger than the benefit otherwise.

chglcu
May 17, 2007

I'm so bored with the USA.
If a reader writer lock isn’t at least as efficient as an exclusive lock in situations where it’s appropriate, it shouldn’t be provided. The alternative is idiotic. But we inhabit an absolutely idiotic reality, so…

Volguus
Mar 3, 2009
This entire thing I've inherited looks like white-papers promising the silver-bullet, never delivering on it and just being taken at face value. Quite promising indeed.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Volguus posted:

This entire thing I've inherited looks like white-papers promising the silver-bullet, never delivering on it and just being taken at face value. Quite promising indeed.
New subtitle of the thread.

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.

Winter Stormer posted:

I futzed with it a little further just now and did manage to break my build by setting cmake_version_required < version 3.3. Since that function sets CMake policy versions, I went looking at what policies 3.3 added, and I'm pretty certain you're running into the problem fixed by https://cmake.org/cmake/help/latest/policy/CMP0060.html. Try setting your minimum to be 3.3 or better.

I checked out the commit that had me pulling my hair out, set cmake_minimum_required to (VERSION 3.16), and everything worked. That would have saved me about 2 hours of trying things and deep diving on how CMake chooses how to interpret linker flags.

Thanks!

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

roomforthetuna posted:

Cool, thanks! So theoretically you should use reader-writer locks, but in reality you should just use exclusive locks unless you're pretty sure you have a good reason to go readwrite, because the cognitive overhead of the more complicated lock and the probable implementation quality difference are likely bigger than the benefit otherwise.

Yeah, so, if you have multiple competing reader threads and a slow but rare critical section in a writer, even a lazily-implemented reader-writer lock will have the inherent advantage of letting the reader threads make progress concurrently. So if that’s the structure of your problem, reader-writer locks can be a good solution.

There are four main problems with reader-writer locks:
  • They’re rarely implemented ideally. There is a level of efficiency that you can get with mutexes if you have direct support in your threading library for the kinds of atomic waiting that mutexes want to do. This is usually only provided for simple, non-recursive mutexes and not for more complex locks, which must be implemented in terms of more basic primitives, and so are necessarily less efficient.
  • The priority inversion thing is a big problem in environments that heavily use thread priorities.
  • Even with an ideal implementation, they’re not going to be faster than mutexes because they have basically the same ordering requirements. So if you have relatively short critical sections, your performance under contention is going to dominated by memory contention and other lock overheads, so you don’t get significant benefits from the theoretically better throughout. And of course you should be aiming to have short critical sections.
  • If you do have long, complicated writes and many concurrent reads, and you are interested in putting effort into optimizing concurrent throughout, it is usually much better to move to a pattern like RCU if you possibly can.

So I see reader-writer locks as, at best, a temporary stopgap that can be introduced fairly easily and feels a lot better but usually doesn’t pay off very well and comes with a lot of drawbacks; and at worst, an attractive nuisance.

rjmccall fucked around with this message at 03:50 on Oct 2, 2021

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

roomforthetuna posted:

Are the boost synchronization primitives compatible with clang thread safety annotations like GUARDED_BY, LOCKS_EXCLUDED, etc.? Those things are great for preventing you from accidentally trying to double-lock.

The clang annotations work with everything that has an appropriate API. You could theoretically even use them for checking things other than locking correctness.

Adbot
ADBOT LOVES YOU

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Plorkyeran posted:

The clang annotations work with everything that has an appropriate API. You could theoretically even use them for checking things other than locking correctness.
Ah, I thought that was not the case because I saw this in various places.
code:
// NOTE: Wrappers for std::mutex and std::unique_lock are provided so that
// we can annotate them with thread safety attributes and use the
// -Wthread-safety warning with clang. The standard library types cannot be
// used directly because they do not provided the required annotations.
Is that behavior outdated now, or do you mean "it works with everything provided you put a wrapper around the thing"? (I've only used it with absl::Mutex where it was all done for me)

Digging around, I found someone suggesting that std::mutex doesn't need wrapping now (if you compile with --stdlib=libc++), but I wasn't able to get it to work in a few minutes of attempting it.

code:
test.cc:6:24: warning: 'guarded_by' attribute requires arguments whose type
is annotated with 'capability' attribute; type here is 'std::mutex' [-Wthread-safety-attributes]
  int x __attribute__((guarded_by(mu))) = 1;

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply