Тёмный
Zen Sepiol
Zen Sepiol
Zen Sepiol
Подписаться
Hi, I'm Zen Sepiol,

I'll talk about C++ and software development in general.

I love code and I love software. Especially the hidden part (backend) where all the magic happens. Stay if you are as interested in uncompromised performance and sustainable designs as I am. Not all software is web or scripts and at its core everything needs to be fast. So join me in discovering the world of C++.

All code related to this channel can be found on github (github.com/ZenSepiol/ZenSepiol)
How to write Thread Pools in C++
13:37
Год назад
How to use multithreading in C++
17:59
2 года назад
How to write better classes in C++
15:08
2 года назад
Комментарии
@KiraOmori
@KiraOmori 25 дней назад
Thank you so much for this! Very clear and quick tutorial :D
@JurekOK
@JurekOK Месяц назад
why is C++ so complicated?
@KZeroJuan
@KZeroJuan Месяц назад
I haven't tried yet.. but thanks.. this was what I was searching for.. and didn't know it was even possible.
@ScaryHutmanPictures
@ScaryHutmanPictures Месяц назад
2:52 possibly undefined behaviour/bug. You are calling queue.front() which returns a reference to the first element. Then you .pop() the first element and your func reference may become invalid.
@SabineS-y9z
@SabineS-y9z Месяц назад
Hey, great video! Can you please show the commands to run the test. Unfortunately the terminal is hidden behind you
@SabineS-y9z
@SabineS-y9z Месяц назад
Hey, great video! at the end you show how to run the test. WHAT ARE THE COMMANDS YOU TYPED??
@levinlasrado4675
@levinlasrado4675 2 месяца назад
Man you deserve so much more recognition, Please promote your channel via Instagram reels or other platforms.
@Antagon666
@Antagon666 2 месяца назад
Well, but it's really not polymorphic in the true sense of the word. Can't put different objects into vector and iterate over them whilst expecting polymorphism.
@SillySussySally
@SillySussySally 2 месяца назад
if you want performance you go CUDA and ironically all you need are barriers and atomics, no thread pool, no semaphores, no conditional variables, no latches, no nothin. CUDA is stupid powerful and so much easier to program, if you can believe it.
@SillySussySally
@SillySussySally 2 месяца назад
yeah, I thought it was harder to program in CUDA but that's because I read articles and tutorials from people that don't know what they're doing.
@ZenSepiol
@ZenSepiol 2 месяца назад
@SillySussySally I love Cuda as well. But remember, not everything has a GPU.
@SillySussySally
@SillySussySally 2 месяца назад
@@ZenSepioltrue, but if you want performance, as a consumer, you go full gpu.
@sedenion9524
@sedenion9524 2 месяца назад
If the heavy computation is an opengl GPU render, how to deal with it ?
@MihaiNicaMath
@MihaiNicaMath 2 месяца назад
Another way to do this (which also works on Mac) is to use the "Source Record" plugin for OBS. This lets you create a seperate file name for each source file in your scene, so you can record any/all of them seperately (in addition to the usual entire scene recording). There is a nice tutorial on the "TroubleShoot" RU-vid channel called "Recording seperate sources at FULL QUALITY" that has a tutorial on this.
@muzzawood
@muzzawood 2 месяца назад
Thank for this :) The bat file was getting a bit stuck on the scene selection of the 2 but I can manually deal with that
@muzzawood
@muzzawood 2 месяца назад
got it! just needed to change --scene to --collection Thanks again
@chankayau
@chankayau 3 месяца назад
thanks for the effort
@ChrisWestPhotoEdits
@ChrisWestPhotoEdits 3 месяца назад
This is really useful thank you. Do you, or anyone else, know how to start the two instances recording on a Mac? I've got my two profiles and scenes for screen and webcam, both have the same hotkeys to start and stop recording. I can open two instances of OBS but the hotkeys only work for the instance that has focus.
@ZenSepiol
@ZenSepiol 3 месяца назад
Can‘t help with that, I don’t use Mac.
@t.p.2305
@t.p.2305 3 месяца назад
Very good explanation!
@mohamedhussien4013
@mohamedhussien4013 3 месяца назад
Thank u so much. Magnificent 🤩
@mohamedhussien4013
@mohamedhussien4013 3 месяца назад
Great tutorial. Thank you so much.
@namanbarna394
@namanbarna394 3 месяца назад
In C++ the base optimization struct is known as std::_Compressed_pair
@redve390
@redve390 3 месяца назад
your video helped me A LOT understand how does meson subfile system works. Thank you <3
@AmalgamAsh
@AmalgamAsh 4 месяца назад
I HAVE to try this. I've been using Action!4K to record webcam and mic separately from gameplay but if this is doable in OBS then I may finally have a viable workflow in Obs and things might just run a little tighter for once. And maybe just maybe the sources won't automatically change on me pre- or mid-recording. UGH. Anyways, thank you for this !
@isodoubIet
@isodoubIet 4 месяца назад
The Achilles heel of Dear ImGui is the font rendering. It's unacceptably bad. Subpixel rendering is an absolute must for any serious graphical UI.
@jhummelgaard9310
@jhummelgaard9310 4 месяца назад
Thank you!!
@sayuri_lyssa_channie
@sayuri_lyssa_channie 4 месяца назад
Thank you so much! Finally I know how to do it, thanks man!
@sergeykolesnik1171
@sergeykolesnik1171 4 месяца назад
Very misleading about constexpr. Your example will be fully evaluated at compile time with optimization enabled. And constexpr doesn't guarantee compile time evaluation, unless you use it within a const context (template argument evaluation), or declare the result variable as constexpr.
@sangpark7656
@sangpark7656 5 месяцев назад
hey this is super interesting! I love how video is structured too.
@user-wn4wk3gq3k
@user-wn4wk3gq3k 5 месяцев назад
ImGui + ?
@captainnelson9833
@captainnelson9833 5 месяцев назад
The best explanation of this I've ever heard. Thank you!
@janwilmans5954
@janwilmans5954 5 месяцев назад
no need to use bind: template <typename Fn> auto AddTask(Fn fn) { auto pTask = std::make_shared<std::packaged_task<decltype(fn())()>>(fn); auto f = pTask->get_future(); Add([pTask]() { (*pTask)(); }); return f; }
@eladon19153
@eladon19153 Месяц назад
But then wouldn't you be fixated to no argument (I mean, return_type(void)) functions? I might be wrong, but how can we make it so we could actually send functions with arguments?
@janwilmans5954
@janwilmans5954 5 месяцев назад
You do not need to use packaged_task, you can just pass a lambda to std::thread, std::thread thread([]() { // code here }));
@janwilmans5954
@janwilmans5954 5 месяцев назад
spurious wake ups are not bugs, for example you can get a spurious wakeup when a laptop comes out of sleep mode, there is literally no other way to handle that without re-checking the condition
@TopogyOfficial
@TopogyOfficial 5 месяцев назад
Thank you for the tutorial. This was very helpful and easy to follow. 👌
@b5a5m5
@b5a5m5 5 месяцев назад
Hmm, is Godot considered a small project? This is what they use for their build system.
@gofudgeyourselves9024
@gofudgeyourselves9024 4 месяца назад
Godot Game Engine
@Chevifier
@Chevifier Месяц назад
I usually build double precision build of it and it takes roughly 5-10 minutes to build. and I have a beefy workstation (Ryzen 9 5950X) I honestly dont have anything to compare it to so I didnt have a problem with the build time.
@bennguyen1313
@bennguyen1313 6 месяцев назад
What do you normally use for writing GUI applications? I tried wxWidgets but would like to try GTK because it has an editor (Glade/Cambalache). However, not sure what I need to install.. Meson, MSYS2, GTKMM vs GTK4 vs GTK3 etc. For example, I have Visual Studio Community do I still need MSYS2 (pacman -S mingw-w64-x86_64-toolchain base-devel etc) ? or can I just unzip the GTK source and build using VS? Do I need gvsbuild (Visual Studio Project or Meson Project) ? Also for testing , do you recommend CppUTest, google test , catch2, doctest, ??
@ZenSepiol
@ZenSepiol 6 месяцев назад
For testing I use Catch2. For GUI apps either Dear ImGui or QT. I have a video for Dear Imgui which explains what packages you need.
@LatchGameDev
@LatchGameDev 6 месяцев назад
Thanks it worked 👍
@JorgeVila
@JorgeVila 6 месяцев назад
Worked perfect mate, congrats!
@AnishPednekar
@AnishPednekar 6 месяцев назад
I'm reading a very large csv file (~500mb) and making a sweeping animated plot using ImPlot. This is really helpful to offload the csv parsing to a separate thread. Thanks! I have a question though, how is future_result.wait_for not blocking the GUI thread? Is it skipped over if the task is not yet complete and then re run at the next iteration of Update()?
@ZenSepiol
@ZenSepiol 6 месяцев назад
Yes exactly. It is possible to specify a timeout, when the future will return. No timeout means it returns immediately in case the background job has not finished processing.
@igorstasenko9183
@igorstasenko9183 6 месяцев назад
the most funny part is justification of replacing a single virtual call with templated trick.. - for performance! you saved maybe 2 CPU cycles. may the future generations remember your historical deed! :)))
@ZenSepiol
@ZenSepiol 6 месяцев назад
It’s unnecessary, but fun. 😄
@Dziaji
@Dziaji 6 месяцев назад
This actually doesn't work. It completely removes the point of a virtual function to begin with. The problem is that all the derived types will now have different base types. Usually, the point of a virtual function is so you can have an array of base type pointers, and by calling the virtual function from the base type pointer, each object "knows" its derived type and calls the corresponding function. Using the way he describes in this video, you can't make an array of base types, because each derived type has its own unique base type, so you have to make an array for each derived type, and if you have separate arrays for each type, you might as well make each array with its own derived type, so the concept of a virtual function becomes pointless. Using his example, you might as well make the template function take "(T* obj)" as a parameter instead of "(Base<T> *obj)". The CRTP technique CAN be used to speed up virtual functions a bit, but you have to add another non-template base class that your crtp class inherits from so that all the cinstances can be casted to the same type to make an array, and you have to create a function pointer as a member, and in the constructor of the derived class, you set that pointer equal to a static function defined in the derived class. This means that the runtime will not have to do a lookup to figure out which dervied class type to use, the object will have the function pointer as one of its own data members. There are a couple points to take into consideration for this method: - It will not be as fast as a non virtual function call, because of the fact that the location of the function is not known at compile time, so you have an indirection where the pointer needs to be accessed before the function is called, but since you are probably about to access other members of that object anyway, the value of the pointer is probably already cached (or was about to be cached) so it won't even add an additional RAM access, so it is super fast compared to doing a lookup for that function pointer by first accessing the virtual method table. - if you only have 1 or 2 virtual functions using this method, you will save ram over the standard virtual function scheme, because each object will have 1 extra pointer, and that would be the case with a virtual function as well, but since this method has no virtual function table, you save on RAM. However, each additional pseudo-virtual function you create in this way will add another pointer to every instance, while virtual functions will continue to only add a single pointer to each instance, so it could end up wasting a lot of RAM, so in that case, you are trading RAM for speed. - You have to be careful with the default assignment operator of the base class, because setting a base class instance equal to another will copy the pseudo virtual function pointer as well, and if you are setting a base type equal to a derived type casted to a base type, you will crash if you try to call this virtual method. So to deal with that, you need to explictly implement the assignment operator for your base class and set that pointer equal to the base class's version of the function, and to properly copy a dervied class, you have to use the standard "base *Dervied::Copy()" function, and you can use the pseudo-virtual scheme for that too. - Your pseudo virtual member functions will now be static functions, so you have to call them with the "this" pointer as the first member like you would have to do with C, so to call them, you have to do obj.PseudoVirtualFn(obj, otherParams), but you can get around this by using an intermediate function that does this for you automatically.
@ZenSepiol
@ZenSepiol 6 месяцев назад
Thanks for the elaborate comment! Interfaces and base class pointers are one of the reasons for inheritance. But there are more reasons, e.g. less code, easier maintenance, clear structure, class extensions and quite some more.
@Dziaji
@Dziaji 6 месяцев назад
@@ZenSepiol There are more reasons for inheritance, but there aren't more reasons for virtual functions. Virtual functions were created entirely to keep track of the inherited type from a base pointer. As you showed, you can completely get around virtual functions if you aren't working with base pointers.
@Dziaji
@Dziaji 6 месяцев назад
omg, those eyes! Never seen anything like them.
@ZenSepiol
@ZenSepiol 6 месяцев назад
👀
@niklkelbon3662
@niklkelbon3662 6 месяцев назад
This maybe slowest possible thread pool ever
@n00blamer
@n00blamer 6 месяцев назад
TL;DR - I'd look at the queue first, there should be 10-100x more action per second. Probably a mutex in there, not something wait- or lock free.
@n00blamer
@n00blamer 6 месяцев назад
The real problems begin when you have 30-40 threads; when microbenchmarking they hit the queue too frequently and synchronizing the cache is beginning to be issue. Having N internal queues is also problematic since work stealing or any sort of work balancing will mean communication between threads (=cores) which is memory writing and root cause for the issues. TP + lots of cores + microbenchmarking = bad experience, but in the video's case 3 ms for 1000 tasks is at least 10-30x less than what it should be, that's why the queue is the suspect number one. If this is for "real" work it's roughly 350K tasks per second, if you use this for a game that could potentially run 120 fps that's still 2900 tasks per frame or so, but taking all CPU for one core for the orchestration which is unacceptable. Let's say 10% so ~ 300 tasks per frame, that should get a lot done but it's possible to bump that to 3000-20,000 tasks per frame if needed with some re-structuring of the code but even 1000 tasks sounds stupid amount and wasteful. IDK, it gets a bit muddy here what the use case is going to be but the current code should do alright as it is.
@ZenSepiol
@ZenSepiol 6 месяцев назад
Did you measure? I just ran this on a (very limited) virtual machine, so obviously my numbers are quite low. The code itself should perform decently, but is not optimized for any specific usecase. The best thread pool implementation is heavily depending on the task itself, there are lots of options to optimize with different pros and cons.
@jorik170
@jorik170 7 месяцев назад
idc about the views, this was some nice overview
@laurin__
@laurin__ 7 месяцев назад
thanks youu uwuw, i'll need to research templates futures and mutex stuff first & come back.. ;)) #godblessamerica #wtfisakilometar
@brno322
@brno322 7 месяцев назад
how did you get the intellisense working in your python and scons files? For example `Environment` is underlined in red since the python intellisense thinks it's an undeclared variable
@ZenSepiol
@ZenSepiol 6 месяцев назад
I don’t remember exactly. I probably just turned the squiggly lines of in those files.
@amaama4140
@amaama4140 8 месяцев назад
Yon need to use a teleprompter :)
@ZenSepiol
@ZenSepiol 6 месяцев назад
😅
@SalvatoreBenedetto
@SalvatoreBenedetto 8 месяцев назад
Fantastic video. Hope to see a lot more video on ImGui!
@ZenSepiol
@ZenSepiol 6 месяцев назад
Thanks! Time is tight but I still have some ideas 💡
@bennguyen1313
@bennguyen1313 8 месяцев назад
Any thoughts on JamesBoer / ImFrame? I'd love to try ImGui for a simple one-window gui (no floating/docking etc) that just has a couple textboxes/labels, and a some pushbuttons... a few red/green led-like indicators would be icing on the cake! Any thoughts how easy/hard this would be with Dear ImGui?
@ZenSepiol
@ZenSepiol 6 месяцев назад
This would be rather easy, a couple hours tops.
@quanghungnguyen6261
@quanghungnguyen6261 9 месяцев назад
Thank you, It's very helpful.
@lickguitars1276
@lickguitars1276 9 месяцев назад
i wish you could make a complete tutorial about this specific framework because there is not alot of resources to be found
@ZenSepiol
@ZenSepiol 6 месяцев назад
I‘ll do it as soon as I find the time.
@artursztuc9140
@artursztuc9140 9 месяцев назад
Do you know how to remove the gaps for weekends (or even larger gaps for when the market is closed when you're doing e.g. 1h or 1min candlesticks)?
@ZenSepiol
@ZenSepiol 6 месяцев назад
Would need to look into it. I guess the most sensible thing is to prune the data, e.g. walk through every datapoint and adapt the time. Adjusting the axes is most likely more work.
@leafyoung
@leafyoung 9 месяцев назад
Oh! primitive data member like int will not be default constructed with the default constructor with MyClass(), but with MyClass{}. So, we shall add a constructor if there is primitive data members.