- Why does vector::reserve() not grow exponentially ? - 12 Updates
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 21 04:46PM -0700 On 6/20/2021 11:22 PM, Paavo Helde wrote: >>> involved with std::shared_ptr only cost peanuts. >> What is std::atomic_ptr? > Sorry, I meant std::atomic<int>. Ahh, okay. > In my test, each refcount is a part of a data object which contains a > 256-byte array, so I would say they are isolated pretty well. > If you know how to make the atomic faster, I'm all for it. Isolating the reference count from the data is usually ideal in the general sense. Think of thread A that got a reference and is actively working on something involving the data. Well, shit... Now threads B-D are taking/releasing references during A's work. We would not want any false sharing to occur... If threads B-D mutating the reference count can cause false sharing while thread A is doing its thing, well, that would be bad. Not Good. Also, Capture needs at least memory_order_acquire, and Release needs at least memory_order_release. Also, iirc on an old thread, a very smart person by the name of Alexander Terekhov mentioned something about when the reference count drops to zero, an acquire barrier was needed. But I cannot remember why he said that. Its such an old thread buried in comp.programming.threads. I still do not see exactly why an acquire is needed when the reference count drops to zero. |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 21 05:12PM -0700 On 6/20/2021 11:22 PM, Paavo Helde wrote: >> On 6/20/2021 11:09 AM, Paavo Helde wrote: >>> 19.06.2021 16:08 Sam kirjutas: >>>> Paavo Helde writes: [...] > If you know how to make the atomic faster, I'm all for it. Its not really about making it faster, but trying to amortize it. So, say if you have a linked list of nodes. In certain scenarios, there is no need to make each node have an atomic reference counted smart pointer. That would ruin performance wrt iteration. However, there is an interesting work around. RCU is great, but there is another construction that can be implemented in user-space. Its called proxy collection. I wrote about it here in an older thread. Here is some crude example code: https://pastebin.com/raw/CYZ78gVj Notice how the nodes are not individually reference counted? |
| Juha Nieminen <nospam@thanks.invalid>: Jun 22 05:30AM > One practical example is what your contract says. If it requires your > code to work with portable standard-conforming C++ and not just with a > particular version of g++ then the switch has a practical consequence. That's not a practical example. A practical example is a piece of code, and the result it produces. |
| "Öö Tiib" <ootiib@hot.ee>: Jun 21 11:12PM -0700 On Tuesday, 22 June 2021 at 08:31:14 UTC+3, Juha Nieminen wrote: > > particular version of g++ then the switch has a practical consequence. > That's not a practical example. > A practical example is a piece of code, and the result it produces. For example it added noexcept as part of function signature. There are no purpose of it whatsoever but to break C++14. There was trick of Johannes Schaub that detected if something is constexpr: template<typename T> constexpr typename std::remove_reference<T>::type makeprval(T && t) { return t; } #define isprvalconstexpr(e) noexcept(makeprval(e)) Say I have two functions that do same thing but one of what is efficient run-time other compile time. Examples do not do same thing for demonstration: constexpr int foo_runtime(int) { return 42;} constexpr int foo_compiletime(int num) { return num > 1 ? foo_compiletime(num - 1) * num : 1; } So that worked in C++14: #define foo(X) (isprvalconstexpr(X)?foo_compiletime(X):foo_runtime(X)) int main(int argc, char *argv[]) { int a = 1; const int b = 2; constexpr int c = 3; const int d = argc; std::cout << foo(a) << std::endl; std::cout << foo(b) << std::endl; std::cout << foo(c) << std::endl; std::cout << foo(d) << std::endl; } It did output: 42 2 6 42 It does not work in C++17, also there are no way to detect if something is constexpr or not. |
| MrSpook_D_a3U17y@j_az.net: Jun 22 07:14AM On Mon, 21 Jun 2021 23:12:23 -0700 (PDT) >On Tuesday, 22 June 2021 at 08:31:14 UTC+3, Juha Nieminen wrote: >template<typename T> >constexpr typename std::remove_reference<T>::type makeprval(T && t) I wonder if the C++ committee will one day realise thats its unintelligable gibberish like this that is putting graduates off learning C++. Which is fine for us old timers as there are more job vacancies, but for the language itself its bad news long term. |
| Paavo Helde <myfirstname@osa.pri.ee>: Jun 22 10:56AM +0300 22.06.2021 02:46 Chris M. Thomasson kirjutas: > cannot remember why he said that. Its such an old thread buried in > comp.programming.threads. I still do not see exactly why an acquire is > needed when the reference count drops to zero. This test was meant to measure the overhead of std::atomic<int> over int when used as a reference counter. In the test, there is actually no need for std::atomic<int> as each refcount is accessed only in a a single thread. So using the right memory barriers is not actually important, I chose std::memory_order_relaxed only because it ought to be theoretically fastest. My test showed that even with that theoretically fastest option using the std::atomic<int> involves heavy penalties over simple int (over 4x slower) and std::shared_ptr with all its bells and whistles is only slightly slower than std::atomic<int>. For me, this means there is no need for me to actually use std::atomic<int>. I will continue to use plain int refcounter for single-threaded smartpointers and std::shared_ptr for multithreaded smartpointers, as I have done so far. |
| Juha Nieminen <nospam@thanks.invalid>: Jun 22 08:03AM > There was trick of Johannes Schaub that detected if something is constexpr: > It does not work in C++17, also there are no way to detect if > something is constexpr or not. Good answer, but to the wrong question. The original claim was that C++17 made many things UB that weren't before. I was asking for practical examples where that makes a difference. Your example is exemplifying a difference between the language versions that's not related to UB. |
| "Öö Tiib" <ootiib@hot.ee>: Jun 22 01:28AM -0700 On Tuesday, 22 June 2021 at 11:03:53 UTC+3, Juha Nieminen wrote: > I was asking for practical examples where that makes a difference. > Your example is exemplifying a difference between the language versions > that's not related to UB. Why you move goalposts? If something is stated to be formally UB then it is. It does not matter that it appears to work in actual implementations as in any next patch it may stop working. |
| Manfred <noname@add.invalid>: Jun 22 01:49PM +0200 > gibberish like this that is putting graduates off learning C++. Which is fine > for us old timers as there are more job vacancies, but for the language itself > its bad news long term. No, they won't. Instead, they even craft the language around the most obscure constructs. In some one of the many Bjarne's conferences about concepts in C++20 I remember he himself complaining that, in the process of standardization of such a major feature, they had to give up a proposed syntax because of the objections of some committee language lawyer that such syntax would clash with some currently allowed obscure construct - one that Bjarne himself declared had never seen used in real life. "We are on the path to something that could destroy C++. We must get off that path!" |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 22 12:49PM -0700 On 6/22/2021 12:56 AM, Paavo Helde wrote: > std::atomic<int>. I will continue to use plain int refcounter for > single-threaded smartpointers and std::shared_ptr for multithreaded > smartpointers, as I have done so far. Of course a plaint int refcounter is going to be a heck of a lot faster than any one that uses atomic RMW's. So, I am not exactly sure what the point of the test actually is. You need to compare atomic<int> and shared_ptr in a real multi threaded test. |
| Paavo Helde <myfirstname@osa.pri.ee>: Jun 23 01:36AM +0300 22.06.2021 22:49 Chris M. Thomasson kirjutas: > Of course a plaint int refcounter is going to be a heck of a lot faster > than any one that uses atomic RMW's. So, I am not exactly sure what the > point of the test actually is. You are right. I only did the test because Sam claimed an atomic is just as fast as a plain int and there is no point to have a non-atomic single-threaded refcounter. > You need to compare atomic<int> and > shared_ptr in a real multi threaded test. I just did, the test I posted was a real multi-threaded test, albeit accessing each refcounter in a single thread only. The multithread synchronization penalties were the same as for multitthreaded access. The result was that std::shared_ptr was a bit slower than std::atomic<int>, but not much. |
| "Öö Tiib" <ootiib@hot.ee>: Jun 22 03:36PM -0700 On Tuesday, 22 June 2021 at 22:49:56 UTC+3, Chris M. Thomasson wrote: > than any one that uses atomic RMW's. So, I am not exactly sure what the > point of the test actually is. You need to compare atomic<int> and > shared_ptr in a real multi threaded test. The original point of Paavo IIRC was that he needs sometimes reference counting for objects that are processed by single thread of execution. And so std::shared_ptr makes it slow by adding those atomics there. |
| You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment