Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #80243 > unrolled thread
| Started by | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| First post | 2021-06-10 12:18 +0200 |
| Last post | 2021-06-11 17:06 +0200 |
| Articles | 20 on this page of 252 — 51 participants |
Back to article view | Back to comp.lang.c++
Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-10 12:18 +0200
Re: Why does vector::reserve() not grow exponentially ? Bo Persson <bo@bo-persson.se> - 2021-06-10 13:21 +0200
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-10 14:37 +0300
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-10 15:44 +0200
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-10 16:39 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-10 16:47 +0200
Re: Why does vector::reserve() not grow exponentially ? Bo Persson <bo@bo-persson.se> - 2021-06-10 22:00 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-10 22:09 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-11 06:57 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-11 13:16 +0200
Re: Why does vector::reserve() not grow exponentially ? Bo Persson <bo@bo-persson.se> - 2021-06-11 13:27 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-11 13:53 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-11 19:12 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 04:09 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-12 08:50 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 15:43 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-12 18:59 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-13 07:31 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-13 08:09 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-13 14:12 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-13 09:50 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-13 16:05 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-13 11:23 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-13 18:56 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-13 13:37 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-14 05:16 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-14 07:00 -0400
Re: Why does vector::reserve() not grow exponentially MrSpook_t0Y6kgpd5@3dryi7no.gov - 2021-06-13 08:39 +0000
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-11 19:11 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 04:10 +0200
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-11 22:18 -0700
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 08:18 +0200
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-12 01:43 -0700
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 11:00 +0200
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-12 02:04 -0700
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 11:15 +0200
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-12 02:24 -0700
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 11:30 +0200
Re: Why does vector::reserve() not grow exponentially ? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2021-06-12 12:59 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 13:27 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 13:19 +0200
Re: Why does vector::reserve() not grow exponentially ? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2021-06-12 13:30 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 13:39 +0200
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-12 14:04 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 15:30 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-12 08:53 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 15:31 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-12 18:43 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-13 07:31 +0200
Re: Why does vector::reserve() not grow exponentially ? Richard Damon <Richard@Damon-Family.org> - 2021-06-13 07:48 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-13 14:03 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-13 14:12 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-13 11:21 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-13 18:55 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-13 13:38 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-14 05:18 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-14 07:00 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-14 13:08 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-14 18:35 -0400
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-14 22:49 -0700
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-15 08:11 -0400
Re: Why does vector::reserve() not grow exponentially MrSpook_ka1o_g@otuej9sdvqn8a4.gov.uk - 2021-06-15 12:54 +0000
Re: Why does vector::reserve() not grow exponentially "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-15 13:09 -0700
Re: Why does vector::reserve() not grow exponentially MrSpook_b1My5@751smt.edu - 2021-06-16 08:44 +0000
Re: Why does vector::reserve() not grow exponentially Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-16 13:11 +0300
Re: Why does vector::reserve() not grow exponentially MrSpook_p6g@ktmy0vg8lj7jxt.biz - 2021-06-16 10:21 +0000
Re: Why does vector::reserve() not grow exponentially Sam <sam@email-scan.com> - 2021-06-16 06:41 -0400
Re: Why does vector::reserve() not grow exponentially MrSpook_F2ryro5_b@ugk_rvxkkm.gov - 2021-06-16 11:11 +0000
Re: Why does vector::reserve() not grow exponentially Sam <sam@email-scan.com> - 2021-06-16 08:25 -0400
Re: Why does vector::reserve() not grow exponentially Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-16 16:10 +0300
Re: Why does vector::reserve() not grow exponentially David Brown <david.brown@hesbynett.no> - 2021-06-16 15:59 +0200
Re: Why does vector::reserve() not grow exponentially MrSpook_ucGx3e4l@x8gqtuqjwl9z3g.com - 2021-06-16 13:47 +0000
Re: Why does vector::reserve() not grow exponentially scott@slp53.sl.home (Scott Lurndal) - 2021-06-16 15:09 +0000
Re: Why does vector::reserve() not grow exponentially Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-16 17:50 +0200
Re: Why does vector::reserve() not grow exponentially MrSpook_hjesjs@8pot25r5sg1xe.info - 2021-06-16 15:45 +0000
Re: Why does vector::reserve() not grow exponentially Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-16 21:08 +0300
Re: Why does vector::reserve() not grow exponentially scott@slp53.sl.home (Scott Lurndal) - 2021-06-16 19:06 +0000
Re: Why does vector::reserve() not grow exponentially Juha Nieminen <nospam@thanks.invalid> - 2021-06-16 13:09 +0000
Re: Why does vector::reserve() not grow exponentially ? Manfred <noname@add.invalid> - 2021-06-15 20:30 +0200
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-16 04:33 +0000
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 10:35 +0200
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 11:18 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_u_kch7_3@abbbp5z5c0iw8rwgxg4.gov - 2021-06-16 09:34 +0000
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 11:53 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_ge@ldwlviy1f9uwd19thc.gov - 2021-06-16 10:19 +0000
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 13:09 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_3_fdyox@sg5nvjmv741xbigdp6.info - 2021-06-16 09:04 +0000
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-16 09:20 +0000
Re: Why does vector::reserve() not grow exponentially ? Tim Woodall <news001@woodall.me.uk> - 2021-06-16 09:49 +0000
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 13:14 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_G1Sw6pdcqz@5a69.edu - 2021-06-16 11:25 +0000
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 14:43 +0200
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 14:44 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_g3w@2ur2yrijxtw7d3jt394yu9dp.org - 2021-06-16 13:48 +0000
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 16:07 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_74D@ov88_wt8h.co.uk - 2021-06-16 13:54 +0000
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 19:55 +0200
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-16 13:14 +0000
Re: Why does vector::reserve() not grow exponentially ? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-06-16 10:38 -0400
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-16 19:58 +0200
Re: Why does vector::reserve() not grow exponentially ? "daniel...@gmail.com" <danielaparker@gmail.com> - 2021-06-17 13:45 -0700
Re: Why does vector::reserve() not grow exponentially ? Real Troll <real.troll@trolls.com> - 2021-06-17 21:15 +0000
Re: Why does vector::reserve() not grow exponentially ? Manfred <noname@add.invalid> - 2021-06-18 15:23 +0200
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-18 08:56 +0200
Re: Why does vector::reserve() not grow exponentially ? "daniel...@gmail.com" <danielaparker@gmail.com> - 2021-06-18 08:06 -0700
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-18 17:41 +0200
Re: Why does vector::reserve() not grow exponentially ? "daniel...@gmail.com" <danielaparker@gmail.com> - 2021-06-18 14:31 -0700
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-19 02:53 -0700
Re: Why does vector::reserve() not grow exponentially ? Ian Collins <ian-news@hotmail.com> - 2021-06-19 11:10 +1200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_gavL@es9w71p.tv - 2021-06-18 15:53 +0000
Re: Why does vector::reserve() not grow exponentially ? scott@slp53.sl.home (Scott Lurndal) - 2021-06-18 16:06 +0000
Re: Why does vector::reserve() not grow exponentially ? MrSpook_Zp_@opm5ve6jyhq.ac.uk - 2021-06-18 09:22 +0000
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-16 04:55 -0700
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-16 13:16 +0000
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-16 11:03 -0700
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-17 05:35 +0000
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-17 16:51 -0700
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-17 20:19 -0400
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-17 18:22 -0700
Re: Why does vector::reserve() not grow exponentially ? MrSpook_6a2az@yxcggolr9p.com - 2021-06-18 09:24 +0000
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-18 08:20 -0400
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-18 15:38 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-18 18:01 -0400
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-19 12:32 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-19 09:12 -0400
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-19 15:24 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-19 17:33 -0400
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-20 09:45 +0200
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-19 03:33 -0700
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-19 09:38 -0400
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-19 12:50 -0700
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-19 17:46 -0400
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-20 05:19 -0700
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-19 23:27 +0300
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-19 17:50 -0400
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-19 16:44 -0700
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-18 17:46 +0300
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-18 17:41 -0400
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-19 11:21 +0300
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-19 09:08 -0400
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-20 21:09 +0300
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-20 11:59 -0700
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-20 22:02 +0300
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-20 14:56 -0700
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-21 09:22 +0300
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-21 16:46 -0700
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-22 10:56 +0300
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-22 12:49 -0700
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-23 01:36 +0300
Re: Why does vector::reserve() not grow exponentially ? scott@slp53.sl.home (Scott Lurndal) - 2021-06-23 14:32 +0000
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-23 16:55 +0200
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-24 16:13 -0700
Re: Why does vector::reserve() not grow exponentially ? scott@slp53.sl.home (Scott Lurndal) - 2021-06-25 14:34 +0000
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-25 12:16 -0700
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-22 15:36 -0700
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-24 16:09 -0700
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-21 17:12 -0700
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-20 19:03 -0400
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-21 09:52 +0300
Re: Why does vector::reserve() not grow exponentially ? red floyd <no.spam.here@its.invalid> - 2021-06-18 00:18 -0700
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-18 02:06 -0700
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-21 12:43 +0000
Re: Why does vector::reserve() not grow exponentially ? Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-06-21 22:48 +0100
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-22 05:30 +0000
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-21 23:12 -0700
Re: Why does vector::reserve() not grow exponentially ? MrSpook_D_a3U17y@j_az.net - 2021-06-22 07:14 +0000
Re: Why does vector::reserve() not grow exponentially ? Manfred <noname@add.invalid> - 2021-06-22 13:49 +0200
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-22 08:03 +0000
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-22 01:28 -0700
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-23 06:19 +0000
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-23 04:18 -0700
Re: Why does vector::reserve() not grow exponentially ? Juha Nieminen <nospam@thanks.invalid> - 2021-06-21 12:39 +0000
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-15 08:01 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-15 08:12 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-15 15:34 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-15 17:37 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-16 02:17 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-15 21:11 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-16 07:09 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-16 06:37 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-16 13:01 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-16 08:16 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-16 15:35 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-16 17:40 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-16 13:40 +0200
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-16 18:10 +0300
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-16 14:37 +0300
Re: Why does vector::reserve() not grow exponentially ? scott@slp53.sl.home (Scott Lurndal) - 2021-06-16 15:04 +0000
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-16 17:37 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-16 17:40 -0400
Re: Why does vector::reserve() not grow exponentially ? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-06-16 16:25 -0700
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-16 23:17 -0400
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-17 09:22 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_e0mt@hszpo62mi.com - 2021-06-17 08:31 +0000
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-17 07:11 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-17 09:24 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-17 16:43 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-13 08:11 -0400
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-13 08:10 -0400
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-12 14:01 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 15:34 +0200
Re: Why does vector::reserve() not grow exponentially ? Ian Collins <ian-news@hotmail.com> - 2021-06-13 13:01 +1200
Re: Why does vector::reserve() not grow exponentially ? Öö Tiib <ootiib@hot.ee> - 2021-06-13 07:39 -0700
Re: Why does vector::reserve() not grow exponentially ? Bo Persson <bo@bo-persson.se> - 2021-06-12 10:51 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 11:03 +0200
Re: Why does vector::reserve() not grow exponentially ? Bo Persson <bo@bo-persson.se> - 2021-06-12 13:07 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 13:22 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-12 08:52 -0400
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-10 16:51 -0700
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-11 09:52 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-11 13:17 +0200
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-11 13:45 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-11 13:54 +0200
Re: Why does vector::reserve() not grow exponentially ? David Brown <david.brown@hesbynett.no> - 2021-06-11 15:58 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-11 16:35 +0200
Re: Why does vector::reserve() not grow exponentially ? Manfred <noname@add.invalid> - 2021-06-11 17:11 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-11 17:12 +0200
Re: Why does vector::reserve() not grow exponentially ? Christian Gollwitzer <auriocus@gmx.de> - 2021-06-11 21:15 +0200
Re: Why does vector::reserve() not grow exponentially ? Bo Persson <bo@bo-persson.se> - 2021-06-11 21:58 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-12 04:11 +0200
Re: Why does vector::reserve() not grow exponentially ? Sam <sam@email-scan.com> - 2021-06-11 06:55 -0400
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-11 13:19 +0200
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-10 16:51 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_sw@08_cl170xu11o4f8xcg45.co.uk - 2021-06-10 15:25 +0000
Re: Why does vector::reserve() not grow exponentially ? Bonita Montero <Bonita.Montero@gmail.com> - 2021-06-10 18:18 +0200
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-10 22:40 +0300
Re: Why does vector::reserve() not grow exponentially ? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2021-06-10 22:35 +0200
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-11 09:23 +0300
Re: Why does vector::reserve() not grow exponentially ? Bo Persson <bo@bo-persson.se> - 2021-06-11 12:02 +0200
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-11 03:05 -0700
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-11 03:22 -0700
Re: Why does vector::reserve() not grow exponentially ? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2021-06-11 12:25 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_4421gcxq@fceufv2.ac.uk - 2021-06-11 11:39 +0000
Re: Why does vector::reserve() not grow exponentially ? MrSpook_3wcC2u9@cns8.net - 2021-06-11 10:18 +0000
Re: Why does vector::reserve() not grow exponentially ? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-06-11 03:27 -0700
Re: Why does vector::reserve() not grow exponentially ? MrSpook_4bkzrb03@tu45utvus6nuc.tv - 2021-06-11 10:17 +0000
Re: Why does vector::reserve() not grow exponentially ? Manfred <noname@add.invalid> - 2021-06-11 13:22 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_0nG@p900whw6_n8r7ovwuul.ac.uk - 2021-06-11 11:34 +0000
Re: Why does vector::reserve() not grow exponentially ? Manfred <noname@add.invalid> - 2021-06-11 14:14 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_p_5Ko4g@21yhpi_n4fck_wfz.org - 2021-06-11 12:50 +0000
Re: Why does vector::reserve() not grow exponentially ? MrSpook_0sk4i3p@b1km5k73i1.edu - 2021-06-11 09:24 +0000
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-11 14:18 +0300
Re: Why does vector::reserve() not grow exponentially ? Bo Persson <bo@bo-persson.se> - 2021-06-11 11:59 +0200
Re: Why does vector::reserve() not grow exponentially ? MrSpook_jyc2xeWf9@aw55u6.gov - 2021-06-11 10:17 +0000
Re: Why does vector::reserve() not grow exponentially ? MrSpook_3dnim@5ooodqy.co.uk - 2021-06-11 09:19 +0000
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-11 14:26 +0300
Re: Why does vector::reserve() not grow exponentially ? MrSpook_35@s879vvmwpgee7rpqv.net - 2021-06-11 11:38 +0000
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-11 15:14 +0300
Re: Why does vector::reserve() not grow exponentially ? MrSpook_uQjuVe@5szcyauh_pjzi228wvwn.info - 2021-06-11 12:52 +0000
Re: Why does vector::reserve() not grow exponentially ? Paavo Helde <myfirstname@osa.pri.ee> - 2021-06-11 16:37 +0300
Re: Why does vector::reserve() not grow exponentially ? MrSpook_9fpRQm@i1z834r.net - 2021-06-11 14:58 +0000
Re: Why does vector::reserve() not grow exponentially ? Manfred <noname@add.invalid> - 2021-06-11 17:06 +0200
Page 8 of 13 — ← Prev page 1 … 6 7 [8] 9 10 … 13 Next page →
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2021-06-20 21:09 +0300 |
| Message-ID | <sao09m$b9k$1@dont-email.me> |
| In reply to | #80511 |
19.06.2021 16:08 Sam kirjutas:
> Paavo Helde writes:
>
>> For me, the biggest drawback of std::shared_ptr is that it is
>> multithread-safe. This means that it has to contain some thread
>> synchronization, however
>
> The thread synchronization should be nothing beyond keeping the
> reference counter as a std::atomic object. Nothing more should be
> needed, for 99% of the use cases. Some kind of locking is needed to
> support weak references, that's the only situation where actual locking
> is needed.
>
> But, for garden-variety smart pointers, an atomic counter is all that's
> needed whose overhead is quite negligible.
>
>> Compared with the expense of that, the amount of pointers (1 or 2),
>> even the number of dynamic allocations (1 or 2) pale in comparison
>> (the dynamic allocations happen much more rarely then refcount updates).
>
> Well the amount of pointers becomes a factor here not merely because of
> the smart pointer itself, but because of shared_ptr dumb design, of
> using two pointers instead of one.
>
>> So in our codebase there is a custom non-synchronized smart-pointer
>> used for all the "data" classes (as opposed to "entity" classes). And
>> you were right, it is based on intrusive refcounting in a super root
>> class, just because all of the code is under our control anyway.
>
> And if you make it atomic, you'll get thread safety. If you actually go
> ahead and try to measure the additional overhead, I'd be surprised if
> you'd be able to actually measure anything.
Well, I took your word and measured the overheads. I'm foremost
interested in my typical workloads, so that's the scenario I tested: all
cpu cores maxed out, a lot of smart pointer copies intermixed with
memory-heavish calculations. The program output is here (the "result" is
only calculated to ensure all code branches calculate the same thing and
nothing is optimized away).
hardware_concurrency: 16
Async pointer : result =1056964608, total time = 13.4281 s
Atomic pointer : result =1056964608, total time = 24.774 s
std::shared_ptr : result =1056964608, total time = 25.7377 s
std::make_shared: result =1056964608, total time = 25.1681 s
The measured times *contain the data processing*, so this means the
actual synchronized pointer overhead is not 2x, but actually *many
times* more expensive than an async smart pointer.
These results suggest that I was right, any thread synchronization
(including std::atomic_ptr with std::memory_order_relaxed) means heavy
penalties, whereas extra pointers or extra dynamic allocations involved
with std::shared_ptr only cost peanuts.
I guess one should better stop complaining about the shared_ptr design,
it appears to be pretty fine for its intended purpose (safe usage).
The code is below, feel free to try it out on your favorite platform. My
numbers are from MSVC++ 2019, x64 Release build.
------------------------------------
#include <memory>
#include <string>
#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
#include <numeric>
#include <thread>
#include <atomic>
const size_t kChunkSize = 64;
const size_t kNumPointers = 32*1024;
const size_t kNumCopies = 1024;
const int kCycles = 1;
class AsyncBase {
public:
AsyncBase() : refcount(0) {}
virtual ~AsyncBase() {}
void Capture() { ++refcount; }
void Release() { if (--refcount == 0) { delete this; } }
private:
int refcount;
};
class AtomicBase {
public:
AtomicBase() : refcount(0) {}
virtual ~AtomicBase() {}
void Capture() { refcount.fetch_add(1, std::memory_order_relaxed); }
void Release() { if (refcount.fetch_sub(1,
std::memory_order_relaxed)==1) { delete this; } }
private:
std::atomic<int> refcount;
};
class DummyBase {};
template<typename T>
struct SmartPtr {
public:
SmartPtr() : p(nullptr) {}
SmartPtr(T* x) { if (x) { x->Capture(); } p = x; }
SmartPtr(const SmartPtr& b) { if (b.p) { b.p->Capture(); } p = b.p; }
SmartPtr(SmartPtr&& b) noexcept : p(b.p) { b.p = nullptr; }
~SmartPtr() { if (p) { T* q = p; p = nullptr; q->Release(); } }
SmartPtr& operator=(const SmartPtr& x) { Assign(x.p); return *this; }
SmartPtr& operator=(SmartPtr&& b) noexcept { Move(b.p); return *this; }
T* operator->() { return p; }
T& operator*() { return *p; }
explicit operator bool() const { return !!p; }
private:
void Assign(T* x) {
if (x) {
x->Capture();
}
if (p) {
T* q = p;
p = nullptr;
q->Release();
}
p = x;
}
void Move(T*& x) noexcept {
if (p) {
T* q = p;
p = nullptr;
q->Release();
}
p = x;
x = nullptr;
}
private:
mutable T* p;
};
template<class BASE>
class Data: public BASE {
public:
Data(unsigned int seed) {
std::iota(arr.begin(), arr.end(), seed);
}
unsigned int Process(unsigned int sum) {
for (auto& x : arr) {
sum += x;
++x;
}
return sum;
}
private:
std::array<unsigned int, kChunkSize> arr;
};
template<class DATA, class PTR>
unsigned int ProcessSingleData(PTR p) {
// Make some copies of the pointer:
std::vector<PTR> copies(kNumCopies);
std::fill(copies.begin(), copies.end(), p);
unsigned int sum = 0;
unsigned int shift = 0;
for (auto p : copies) {
sum += p->Process(shift);
++shift;
}
return sum;
}
template<class DATA, class PTR, bool USEMAKESHARED>
unsigned int Work() {
// make some smartpointers.
std::vector<PTR> pointers(kNumPointers);
unsigned int seed = 0;
for (auto& ref : pointers) {
if constexpr (USEMAKESHARED) {
ref = std::make_shared<DATA>(seed);
} else {
ref = PTR(new DATA(seed));
}
++seed;
}
unsigned int result = 0;
for (int i = 0; i < kCycles; ++i) {
for (auto p : pointers) {
result += ProcessSingleData<DATA, PTR>(p);
}
}
return result;
}
template<class DATA, class PTR, bool USEMAKESHARED>
std::pair<unsigned int, double> TimedWork() {
auto start = std::chrono::steady_clock::now();
unsigned int result = Work<DATA, PTR, USEMAKESHARED>();
auto finish = std::chrono::steady_clock::now();
double lapse = std::chrono::duration<double>(finish - start).count();
return std::make_pair(result, lapse);
}
template<class DATA, class PTR, bool USEMAKESHARED=false>
std::pair<unsigned int, double> ThreadedWork(unsigned int numThreads) {
std::vector<unsigned int> results(numThreads);
std::vector<double> lapses(numThreads);
std::vector<std::thread> threads;
for (unsigned int i = 0; i < numThreads; ++i) {
threads.emplace_back([i, &results, &lapses]() {
unsigned int result;
double lapse;
std::tie(result, lapse) = TimedWork<DATA, PTR, USEMAKESHARED>();
results[i] = result;
lapses[i] = lapse;
});
}
for (auto& ref : threads) {
ref.join();
}
unsigned int result = results[0];
for (auto x : results) {
if (x != result) {
throw std::logic_error("checksum differs");
}
}
double totalLapse = std::accumulate(lapses.begin(), lapses.end(), 0.0);
return std::make_pair(result, totalLapse);
}
using AsyncData = Data<AsyncBase>;
using PAsyncData = SmartPtr<AsyncData>;
using AtomicData = Data<AtomicBase>;
using PAtomicData = SmartPtr<AtomicData>;
using SharedData = Data<DummyBase>;
using PSharedData = std::shared_ptr<SharedData>;
int main() {
unsigned int numThreads = std::thread::hardware_concurrency();
std::cout << "hardware_concurrency: " << numThreads << "\n";
unsigned int result;
double lapse;
std::tie(result, lapse) = ThreadedWork<AsyncData, PAsyncData>(numThreads);
std::cout << "Async pointer : result =" << result << ", total time =
" << lapse << " s\n";
std::tie(result, lapse) = ThreadedWork<AtomicData,
PAtomicData>(numThreads);
std::cout << "Atomic pointer : result =" << result << ", total time =
" << lapse << " s\n";
std::tie(result, lapse) = ThreadedWork<SharedData,
PSharedData>(numThreads);
std::cout << "std::shared_ptr : result =" << result << ", total time =
" << lapse << " s\n";
std::tie(result, lapse) = ThreadedWork<SharedData, PSharedData,
true>(numThreads);
std::cout << "std::make_shared: result =" << result << ", total time =
" << lapse << " s\n";
}
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2021-06-20 11:59 -0700 |
| Message-ID | <78a17feb-b51e-4831-be87-65235ef63533n@googlegroups.com> |
| In reply to | #80523 |
On Sunday, 20 June 2021 at 21:10:14 UTC+3, Paavo Helde wrote: > > These results suggest that I was right, any thread synchronization > (including std::atomic_ptr with std::memory_order_relaxed) means heavy > penalties, whereas extra pointers or extra dynamic allocations involved > with std::shared_ptr only cost peanuts. Yes, same was with text processing with those CoW strings. Atomic operations of ref count caused these to be sluggish. Who wants to be quick should be embarrassingly parallel and share only immutable data.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2021-06-20 22:02 +0300 |
| Message-ID | <sao3co$j5$1@dont-email.me> |
| In reply to | #80523 |
20.06.2021 21:09 Paavo Helde kirjutas: > Well, I took your word and measured the overheads. FYI, results from a Linux machine with gcc. The synchronization overhead appears not so large as on Windows, but on the other hand any supposed losses of std::shared_ptr seem to be even smaller, compared to a pure std::atomic<int>: > g++ test1.cpp -std=c++17 -O3 -pthread > ./a.out hardware_concurrency: 16 Async pointer : result =1056964608, total time = 14.7805 s Atomic pointer : result =1056964608, total time = 21.0752 s std::shared_ptr : result =1056964608, total time = 21.427 s std::make_shared: result =1056964608, total time = 21.2404 s
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2021-06-20 14:56 -0700 |
| Message-ID | <saodhr$1at6$1@gioia.aioe.org> |
| In reply to | #80523 |
On 6/20/2021 11:09 AM, Paavo Helde wrote:
> 19.06.2021 16:08 Sam kirjutas:
>> Paavo Helde writes:
>>
>>> For me, the biggest drawback of std::shared_ptr is that it is
>>> multithread-safe. This means that it has to contain some thread
>>> synchronization, however
>>
>> The thread synchronization should be nothing beyond keeping the
>> reference counter as a std::atomic object. Nothing more should be
>> needed, for 99% of the use cases. Some kind of locking is needed to
>> support weak references, that's the only situation where actual
>> locking is needed.
>>
>> But, for garden-variety smart pointers, an atomic counter is all
>> that's needed whose overhead is quite negligible.
>>
>>> Compared with the expense of that, the amount of pointers (1 or 2),
>>> even the number of dynamic allocations (1 or 2) pale in comparison
>>> (the dynamic allocations happen much more rarely then refcount updates).
>>
>> Well the amount of pointers becomes a factor here not merely because
>> of the smart pointer itself, but because of shared_ptr dumb design, of
>> using two pointers instead of one.
>>
>>> So in our codebase there is a custom non-synchronized smart-pointer
>>> used for all the "data" classes (as opposed to "entity" classes). And
>>> you were right, it is based on intrusive refcounting in a super root
>>> class, just because all of the code is under our control anyway.
>>
>> And if you make it atomic, you'll get thread safety. If you actually
>> go ahead and try to measure the additional overhead, I'd be surprised
>> if you'd be able to actually measure anything.
>
> Well, I took your word and measured the overheads. I'm foremost
> interested in my typical workloads, so that's the scenario I tested: all
> cpu cores maxed out, a lot of smart pointer copies intermixed with
> memory-heavish calculations. The program output is here (the "result" is
> only calculated to ensure all code branches calculate the same thing and
> nothing is optimized away).
>
> hardware_concurrency: 16
> Async pointer : result =1056964608, total time = 13.4281 s
> Atomic pointer : result =1056964608, total time = 24.774 s
> std::shared_ptr : result =1056964608, total time = 25.7377 s
> std::make_shared: result =1056964608, total time = 25.1681 s
>
> The measured times *contain the data processing*, so this means the
> actual synchronized pointer overhead is not 2x, but actually *many
> times* more expensive than an async smart pointer.
>
> These results suggest that I was right, any thread synchronization
> (including std::atomic_ptr with std::memory_order_relaxed) means heavy
> penalties, whereas extra pointers or extra dynamic allocations involved
> with std::shared_ptr only cost peanuts.
What is std::atomic_ptr?
>
> I guess one should better stop complaining about the shared_ptr design,
> it appears to be pretty fine for its intended purpose (safe usage).
>
> The code is below, feel free to try it out on your favorite platform. My
> numbers are from MSVC++ 2019, x64 Release build.
>
> ------------------------------------
[...]
> class AtomicBase {
> public:
> AtomicBase() : refcount(0) {}
> virtual ~AtomicBase() {}
> void Capture() { refcount.fetch_add(1, std::memory_order_relaxed); }
> void Release() { if (refcount.fetch_sub(1,
> std::memory_order_relaxed)==1) { delete this; } }
> private:
> std::atomic<int> refcount;
> };
[...]
You have some issues with your memory order here, relaxed is not going
to cut it. Also, better try to isolate the refcount on a cacheline, and
pad it.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2021-06-21 09:22 +0300 |
| Message-ID | <sapb74$pc0$1@dont-email.me> |
| In reply to | #80526 |
21.06.2021 00:56 Chris M. Thomasson kirjutas:
> On 6/20/2021 11:09 AM, Paavo Helde wrote:
>> 19.06.2021 16:08 Sam kirjutas:
>>> Paavo Helde writes:
>>>
>>>> For me, the biggest drawback of std::shared_ptr is that it is
>>>> multithread-safe. This means that it has to contain some thread
>>>> synchronization, however
>>>
>>> The thread synchronization should be nothing beyond keeping the
>>> reference counter as a std::atomic object. Nothing more should be
>>> needed, for 99% of the use cases. Some kind of locking is needed to
>>> support weak references, that's the only situation where actual
>>> locking is needed.
>>>
>>> But, for garden-variety smart pointers, an atomic counter is all
>>> that's needed whose overhead is quite negligible.
>>>
>>>> Compared with the expense of that, the amount of pointers (1 or 2),
>>>> even the number of dynamic allocations (1 or 2) pale in comparison
>>>> (the dynamic allocations happen much more rarely then refcount
>>>> updates).
>>>
>>> Well the amount of pointers becomes a factor here not merely because
>>> of the smart pointer itself, but because of shared_ptr dumb design,
>>> of using two pointers instead of one.
>>>
>>>> So in our codebase there is a custom non-synchronized smart-pointer
>>>> used for all the "data" classes (as opposed to "entity" classes).
>>>> And you were right, it is based on intrusive refcounting in a super
>>>> root class, just because all of the code is under our control anyway.
>>>
>>> And if you make it atomic, you'll get thread safety. If you actually
>>> go ahead and try to measure the additional overhead, I'd be surprised
>>> if you'd be able to actually measure anything.
>>
>> Well, I took your word and measured the overheads. I'm foremost
>> interested in my typical workloads, so that's the scenario I tested:
>> all cpu cores maxed out, a lot of smart pointer copies intermixed with
>> memory-heavish calculations. The program output is here (the "result"
>> is only calculated to ensure all code branches calculate the same
>> thing and nothing is optimized away).
>>
>> hardware_concurrency: 16
>> Async pointer : result =1056964608, total time = 13.4281 s
>> Atomic pointer : result =1056964608, total time = 24.774 s
>> std::shared_ptr : result =1056964608, total time = 25.7377 s
>> std::make_shared: result =1056964608, total time = 25.1681 s
>>
>> The measured times *contain the data processing*, so this means the
>> actual synchronized pointer overhead is not 2x, but actually *many
>> times* more expensive than an async smart pointer.
>>
>> These results suggest that I was right, any thread synchronization
>> (including std::atomic_ptr with std::memory_order_relaxed) means heavy
>> penalties, whereas extra pointers or extra dynamic allocations
>> involved with std::shared_ptr only cost peanuts.
>
> What is std::atomic_ptr?
Sorry, I meant std::atomic<int>.
>
>>
>> I guess one should better stop complaining about the shared_ptr
>> design, it appears to be pretty fine for its intended purpose (safe
>> usage).
>>
>> The code is below, feel free to try it out on your favorite platform.
>> My numbers are from MSVC++ 2019, x64 Release build.
>>
>> ------------------------------------
> [...]
>> class AtomicBase {
>> public:
>> AtomicBase() : refcount(0) {}
>> virtual ~AtomicBase() {}
>> void Capture() { refcount.fetch_add(1, std::memory_order_relaxed); }
>> void Release() { if (refcount.fetch_sub(1,
>> std::memory_order_relaxed)==1) { delete this; } }
>> private:
>> std::atomic<int> refcount;
>> };
> [...]
>
> You have some issues with your memory order here, relaxed is not going
> to cut it. Also, better try to isolate the refcount on a cacheline, and
> pad it.
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.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2021-06-21 16:46 -0700 |
| Message-ID | <sar8c0$v0v$1@gioia.aioe.org> |
| In reply to | #80528 |
On 6/20/2021 11:22 PM, Paavo Helde wrote:
> 21.06.2021 00:56 Chris M. Thomasson kirjutas:
>> On 6/20/2021 11:09 AM, Paavo Helde wrote:
>>> 19.06.2021 16:08 Sam kirjutas:
>>>> Paavo Helde writes:
>>>>
>>>>> For me, the biggest drawback of std::shared_ptr is that it is
>>>>> multithread-safe. This means that it has to contain some thread
>>>>> synchronization, however
>>>>
>>>> The thread synchronization should be nothing beyond keeping the
>>>> reference counter as a std::atomic object. Nothing more should be
>>>> needed, for 99% of the use cases. Some kind of locking is needed to
>>>> support weak references, that's the only situation where actual
>>>> locking is needed.
>>>>
>>>> But, for garden-variety smart pointers, an atomic counter is all
>>>> that's needed whose overhead is quite negligible.
>>>>
>>>>> Compared with the expense of that, the amount of pointers (1 or 2),
>>>>> even the number of dynamic allocations (1 or 2) pale in comparison
>>>>> (the dynamic allocations happen much more rarely then refcount
>>>>> updates).
>>>>
>>>> Well the amount of pointers becomes a factor here not merely because
>>>> of the smart pointer itself, but because of shared_ptr dumb design,
>>>> of using two pointers instead of one.
>>>>
>>>>> So in our codebase there is a custom non-synchronized smart-pointer
>>>>> used for all the "data" classes (as opposed to "entity" classes).
>>>>> And you were right, it is based on intrusive refcounting in a super
>>>>> root class, just because all of the code is under our control anyway.
>>>>
>>>> And if you make it atomic, you'll get thread safety. If you actually
>>>> go ahead and try to measure the additional overhead, I'd be
>>>> surprised if you'd be able to actually measure anything.
>>>
>>> Well, I took your word and measured the overheads. I'm foremost
>>> interested in my typical workloads, so that's the scenario I tested:
>>> all cpu cores maxed out, a lot of smart pointer copies intermixed
>>> with memory-heavish calculations. The program output is here (the
>>> "result" is only calculated to ensure all code branches calculate the
>>> same thing and nothing is optimized away).
>>>
>>> hardware_concurrency: 16
>>> Async pointer : result =1056964608, total time = 13.4281 s
>>> Atomic pointer : result =1056964608, total time = 24.774 s
>>> std::shared_ptr : result =1056964608, total time = 25.7377 s
>>> std::make_shared: result =1056964608, total time = 25.1681 s
>>>
>>> The measured times *contain the data processing*, so this means the
>>> actual synchronized pointer overhead is not 2x, but actually *many
>>> times* more expensive than an async smart pointer.
>>>
>>> These results suggest that I was right, any thread synchronization
>>> (including std::atomic_ptr with std::memory_order_relaxed) means
>>> heavy penalties, whereas extra pointers or extra dynamic allocations
>>> involved with std::shared_ptr only cost peanuts.
>>
>> What is std::atomic_ptr?
>
> Sorry, I meant std::atomic<int>.
Ahh, okay.
>
>>
>>>
>>> I guess one should better stop complaining about the shared_ptr
>>> design, it appears to be pretty fine for its intended purpose (safe
>>> usage).
>>>
>>> The code is below, feel free to try it out on your favorite platform.
>>> My numbers are from MSVC++ 2019, x64 Release build.
>>>
>>> ------------------------------------
>> [...]
>>> class AtomicBase {
>>> public:
>>> AtomicBase() : refcount(0) {}
>>> virtual ~AtomicBase() {}
>>> void Capture() { refcount.fetch_add(1,
>>> std::memory_order_relaxed); }
>>> void Release() { if (refcount.fetch_sub(1,
>>> std::memory_order_relaxed)==1) { delete this; } }
>>> private:
>>> std::atomic<int> refcount;
>>> };
>> [...]
>>
>> You have some issues with your memory order here, relaxed is not going
>> to cut it. Also, better try to isolate the refcount on a cacheline,
>> and pad it.
>
> 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.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2021-06-22 10:56 +0300 |
| Message-ID | <sas52n$c4v$1@dont-email.me> |
| In reply to | #80538 |
22.06.2021 02:46 Chris M. Thomasson kirjutas: > > 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. 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.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2021-06-22 12:49 -0700 |
| Message-ID | <satesi$10dt$1@gioia.aioe.org> |
| In reply to | #80543 |
On 6/22/2021 12:56 AM, Paavo Helde wrote: > 22.06.2021 02:46 Chris M. Thomasson kirjutas: >> >> 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. > > 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. 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.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2021-06-23 01:36 +0300 |
| Message-ID | <satokh$j3p$1@dont-email.me> |
| In reply to | #80547 |
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.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2021-06-23 14:32 +0000 |
| Message-ID | <aCHAI.845208$nn2.365388@fx48.iad> |
| In reply to | #80548 |
Paavo Helde <myfirstname@osa.pri.ee> writes: >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 In the general case, an atomic access will be just as fast as a non-atomic access to the same location. It is only when the atomic is contended for by multiple agents (e.g. cores/threads) that there will be a potential performance impact on the application as other threads contend for the cache line. In both cases, the target location will be cached[*] in a cache local to the core/thread performing the access. The atomic RMW operation is required to ensure that the cache line isn't evicted or invalidated between the R and W, however absent contention, the RMW performs better than separate load/inc/store operations as the RMW operation is actually performed by the cache. Unaligned "atomic" accesses that cross cache lines should be avoided (and generally aren't easy to do from high level languages). [*] Assuming standard user-mode code where the memory type is marked as cachable (write-back or write-through) in the MTRR (intel) or MAIR (ARM) registers.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-06-23 16:55 +0200 |
| Message-ID | <savi15$860$1@dont-email.me> |
| In reply to | #80552 |
On 23/06/2021 16:32, Scott Lurndal wrote: > Paavo Helde <myfirstname@osa.pri.ee> writes: >> 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 > > In the general case, an atomic access will be just > as fast as a non-atomic access to the same location. > That is going to depend on at least four things, perhaps more. (I'm sure you know all these, but perhaps you were making assumptions that aren't necessarily true.) If the memory ordering is anything other than "relaxed", it's likely that the compiler will have to generate synchronisation instructions. For "sequential consistency" ordering, that can mean full flushes of write buffers and pipeline stalls until these are complete. These can lead to significant delays depending on the system and the instructions - I seem to remember reading about figures of up to 200 cycles. The ISA and processor architecture can make a difference. Processors with strong memory ordering can have some of these delays simply due to the locked bus operations, even when "relaxed" ordering is given. (On the other hand, they are usually designed to reduce the cost of sequentially consistent accesses.) If the access is not just a read or a write, but an RMW operation, then on many processors this requires bus locking of some sort, compare-and-swap loops, load-store-exclusive loops, spin locks, or other mechanisms to work correctly. The time taken here is much larger than for accessing a plain int. And if the object being accessed atomically is bigger than the processor can handle as a single access (obviously this won't happen for an "int", except on an 8-bit device), then again you'll need locks or loops of some sort. These all happen even if there is no contention for the variable at the time. > It is only when the atomic is > contended for by multiple agents (e.g. cores/threads) that there > will be a potential performance impact on the application as > other threads contend for the cache line. > > In both cases, the target location will be cached[*] in a cache > local to the core/thread performing the access. The atomic > RMW operation is required to ensure that the cache line isn't > evicted or invalidated between the R and W, however absent > contention, the RMW performs better than separate load/inc/store > operations as the RMW operation is actually performed by the > cache. > > Unaligned "atomic" accesses that cross cache lines should be > avoided (and generally aren't easy to do from high level languages). > > > [*] Assuming standard user-mode code where the memory type is > marked as cachable (write-back or write-through) in the MTRR > (intel) or MAIR (ARM) registers. >
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2021-06-24 16:13 -0700 |
| Message-ID | <sb33io$lt5$2@gioia.aioe.org> |
| In reply to | #80552 |
On 6/23/2021 7:32 AM, Scott Lurndal wrote: > Paavo Helde <myfirstname@osa.pri.ee> writes: >> 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 > > In the general case, an atomic access will be just > as fast as a non-atomic access to the same location. Iirc, an atomic RMW, like a LOCK XADD will be slower than a plain non-atomic access. Even if everything is single threaded. [...]
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2021-06-25 14:34 +0000 |
| Message-ID | <UPlBI.108244$5%7.80698@fx13.iad> |
| In reply to | #80560 |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes: >On 6/23/2021 7:32 AM, Scott Lurndal wrote: >> Paavo Helde <myfirstname@osa.pri.ee> writes: >>> 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 >> >> In the general case, an atomic access will be just >> as fast as a non-atomic access to the same location. > >Iirc, an atomic RMW, like a LOCK XADD will be slower than a plain >non-atomic access. Even if everything is single threaded. Why would you think that? The processor needs to acquire exclusive access to the cache line in order to modify. That is basically an implicit lock, and is done regardless of the LOCK prefix. Modern processors may delegate the XADD operation to the cache rather than loading from the cache, performing the operation, and storing back to cache. Only if the access straddles two cache lines will the system bus lock be acquired (or in very rare cases when the processor cannot acquire the cache line in a certain amount of time after which the processor will assert the bus lock).
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2021-06-25 12:16 -0700 |
| Message-ID | <sb5a36$1eoj$1@gioia.aioe.org> |
| In reply to | #80561 |
On 6/25/2021 7:34 AM, Scott Lurndal wrote:
> "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
>> On 6/23/2021 7:32 AM, Scott Lurndal wrote:
>>> Paavo Helde <myfirstname@osa.pri.ee> writes:
>>>> 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
>>>
>>> In the general case, an atomic access will be just
>>> as fast as a non-atomic access to the same location.
>>
>> Iirc, an atomic RMW, like a LOCK XADD will be slower than a plain
>> non-atomic access. Even if everything is single threaded.
>
> Why would you think that?
Iirc, I did some tests in the past where I ran a large loop of volatile
non-atomic accesses vs LOCK XADD in a single thread and, iirc, the LOCK
XADD was slower. It was something like:
volatile unsigned long target = 0;
for (unsigned long i = 0; i < N; ++i)
{
++target;
}
vs
for (unsigned long i = 0; i < N; ++i)
{
ct_atomic_xadd(&target, 1);
}
This was before C++ made atomics/membars standard.
ct_atomic_xadd was implemented in assembly language and externally
assembled.
>
> The processor needs to acquire exclusive access to the cache line
> in order to modify. That is basically an implicit lock, and is
> done regardless of the LOCK prefix. Modern processors may delegate
> the XADD operation to the cache rather than loading from the cache,
> performing the operation, and storing back to cache.
>
> Only if the access straddles two cache lines will the system bus
> lock be acquired (or in very rare cases when the processor cannot
> acquire the cache line in a certain amount of time after which the
> processor will assert the bus lock).
>
Well, shit. I need to code up the test again to refresh my memory.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2021-06-22 15:36 -0700 |
| Message-ID | <00f10934-ab7d-48f8-ba1b-dc968a17f77fn@googlegroups.com> |
| In reply to | #80547 |
On Tuesday, 22 June 2021 at 22:49:56 UTC+3, Chris M. Thomasson wrote: > On 6/22/2021 12:56 AM, Paavo Helde wrote: > > 22.06.2021 02:46 Chris M. Thomasson kirjutas: > >> > >> 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. > > > > 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. > > 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. 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.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2021-06-24 16:09 -0700 |
| Message-ID | <sb33br$lt5$1@gioia.aioe.org> |
| In reply to | #80549 |
On 6/22/2021 3:36 PM, Öö Tiib wrote: > On Tuesday, 22 June 2021 at 22:49:56 UTC+3, Chris M. Thomasson wrote: >> On 6/22/2021 12:56 AM, Paavo Helde wrote: >>> 22.06.2021 02:46 Chris M. Thomasson kirjutas: >>>> >>>> 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. >>> >>> 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. >> >> 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. > > 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. > Ahhh. Well, iirc, I did one where a thread would get a reference using an atomic RMW. Then, switch over to using reference counting that did not use any atomics. When this non-atomic reference counter dropped to zero, instead of deleting the object, it would decrement the atomic counter. If the atomic ref count went to zero, then the object would be deleted.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2021-06-21 17:12 -0700 |
| Message-ID | <sar9ti$1e0p$1@gioia.aioe.org> |
| In reply to | #80528 |
On 6/20/2021 11:22 PM, Paavo Helde wrote: > 21.06.2021 00:56 Chris M. Thomasson kirjutas: >> 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?
[toc] | [prev] | [next] | [standalone]
| From | Sam <sam@email-scan.com> |
|---|---|
| Date | 2021-06-20 19:03 -0400 |
| Subject | Re: Why does vector::reserve() not grow exponentially ? |
| Message-ID | <cone.1624230195.710773.28697.1004@monster.email-scan.com> |
| In reply to | #80523 |
[Multipart message — attachments visible in raw view] — view raw
Paavo Helde writes: > hardware_concurrency: 16 > Async pointer : result =1056964608, total time = 13.4281 s > Atomic pointer : result =1056964608, total time = 24.774 s > std::shared_ptr : result =1056964608, total time = 25.7377 s > std::make_shared: result =1056964608, total time = 25.1681 s > > The measured times *contain the data processing*, so this means the actual > synchronized pointer overhead is not 2x, but actually *many times* more > expensive than an async smart pointer. > > These results suggest that I was right, any thread synchronization > (including std::atomic_ptr with std::memory_order_relaxed) means heavy > penalties, whereas extra pointers or extra dynamic allocations involved with > std::shared_ptr only cost peanuts. > > I guess one should better stop complaining about the shared_ptr design, it > appears to be pretty fine for its intended purpose (safe usage). It's going to be quite a neat trick to implement shared_ptr without keeping an atomic reference count, somewhere. In fact, digging into shared_ptr's innards what does one find, but an _Atomic_word, whose operations use acquire/release memory ordering which, according to the above, should impose a heavy penalty. Something in your observed results does not add up, in this respect. However, the shortcoming with shared_ptr that I see, and I explained – only a small part of it relates to this specific area.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2021-06-21 09:52 +0300 |
| Message-ID | <sapcvn$32p$1@dont-email.me> |
| In reply to | #80527 |
21.06.2021 02:03 Sam kirjutas: > Paavo Helde writes: > >> hardware_concurrency: 16 >> Async pointer : result =1056964608, total time = 13.4281 s >> Atomic pointer : result =1056964608, total time = 24.774 s >> std::shared_ptr : result =1056964608, total time = 25.7377 s >> std::make_shared: result =1056964608, total time = 25.1681 s >> >> The measured times *contain the data processing*, so this means the >> actual synchronized pointer overhead is not 2x, but actually *many >> times* more expensive than an async smart pointer. >> >> These results suggest that I was right, any thread synchronization >> (including std::atomic_ptr with std::memory_order_relaxed) means heavy >> penalties, whereas extra pointers or extra dynamic allocations >> involved with std::shared_ptr only cost peanuts. >> >> I guess one should better stop complaining about the shared_ptr >> design, it appears to be pretty fine for its intended purpose (safe >> usage). > > It's going to be quite a neat trick to implement shared_ptr without > keeping an atomic reference count, somewhere. In fact, digging into > shared_ptr's innards what does one find, but an _Atomic_word, whose > operations use acquire/release memory ordering which, according to the > above, should impose a heavy penalty. What? Surely the std::shared_ptr must contain thread synchronization, most probably in the form of an atomic. This is also visible from the timings, the std::shared_ptr timings are very similar to std::atomic. And yes, both involve heavy penalty when compared to non-synchronized single-threaded refcount (in case when each refcounted object is only accessed in a single thread like in my test). > Something in your observed results does not add up, in this respect. Not sure what you mean. You said that you would be surprised if making the refcounter atomic would add any measurable overhead, and now you are surprised indeed. I do not see any contradiction :-)
[toc] | [prev] | [next] | [standalone]
| From | red floyd <no.spam.here@its.invalid> |
|---|---|
| Date | 2021-06-18 00:18 -0700 |
| Message-ID | <sahhce$g0b$1@redfloyd.dont-email.me> |
| In reply to | #80487 |
On 6/17/2021 4:51 PM, Öö Tiib wrote: > On Thursday, 17 June 2021 at 08:35:26 UTC+3, Juha Nieminen wrote: >> Öö Tiib <oot...@hot.ee> wrote: >>> and so I'm stuck in C++14. >> My condolences. > > No condolescences are mine ... to those who have to use C++17 and so their > code is formally full of undefined behaviors. > OK, I'm confused. What used to be defined behavior that is now UB?
[toc] | [prev] | [next] | [standalone]
Page 8 of 13 — ← Prev page 1 … 6 7 [8] 9 10 … 13 Next page →
Back to top | Article view | comp.lang.c++
csiph-web