Monday, 22 March 2021

Misc // New PC!


*This is a bit of a long one; I apologise. tldr; New pc with a 3090. Runs perfectly.

So I originally had no plans to upgrade my computer. My boy Kyoya (named after Kyoya Ootori from Ouran Highschool Host Club) was getting dated but still ran Visual Studio and could play most games on high settings with temperatures reaching around 70/75. He has an i7-4790k (base 4ghz) with 16gb DDR3 1600mhz ram and a GTX 980. I bought him back in September 2015 and up till then, he was the beefiest pc I have ever owned. He cost a whopping £1700 and was a pre-built from HP. 

However, in January, Scan had a shipment of Nvidia 3090 FEs and so I impulse bought one because it was in stock. It would not fit in Kyoya's case due to the drive cage and optical drives but also, he has no ventilation (other than exhaust) and pretty much relies on negative pressure. Also, it would've been severely bottlenecked by the 4790k. And so began the hunt for pc parts in a time where there are no pc parts.

I knew immediately I wanted an AMD 5950x but at this point I'm not sure they exist so I settled for the 3950x. I also wanted 128gb of ram but that also didn't exist so I had to settle for 64 (oh no). I did get the motherboard I wanted and the Noctua Chromax Black NH-D15 but failed to research properly and that fan actually blocks the first pcie lane on the Crosshair VIII Formula. I really wanted an air cooler because I think they look cool (pun intended) but ended up with a Corsair Hydro H150i all in one. I've never had an aio before but it's growing on me.


I spent a ridiculous amount of time on the cable management, even though you can't really see it due to the dark tinted glass; I love that you can just see the little bits of rgb in the case from the cooler, gpu and motherboard display.




The new pc is called Archer (after Jonathan Archer from Star Trek Enterprise) and here he is with his little big brother Kyoya who has now become my "minimum specs" testing pc. Side note: This is not the final setup; I was transferring files.

Parts list:
CPU: AMD Ryzen 9 3950X 3.5 GHz 16-Core Processor
CPU Cooler: Corsair iCUE H150i RGB PRO XT 75 CFM Liquid CPU Cooler
Motherboard: Asus ROG Crosshair VIII Formula ATX AM4
Memory: Corsair Vengeance LPX 64 GB (4 x 16 GB) DDR4-3600 CL18
Storage: x2 Samsung 970 Evo 1 TB M.2-2280 NVME Solid State Drive
Storage: Samsung 870 QVO 4 TB 2.5" Solid State Drive
Storage: Seagate BarraCuda Pro 10 TB 3.5" 7200RPM Internal Hard Drive
Video Card: NVIDIA GeForce RTX 3090 24 GB Founders Edition
Case: Fractal Design Define 7 XL Dark ATX Full Tower Case
Power Supply: Fractal Design Ion+ 860 W 80+ Platinum Certified Fully Modular ATX Power Supply 
Case Fans: x3 Noctua Industrial 3000rpm 140mm 
OS: Microsoft Windows 10 Home OEM 64-bit

After some research, I decided to set the ram to a speed of 3200mhz as the 3950x can only work with 3600 when overclocking and I want nothing to do with that; I need this pc to be as stable as possible so OC has been disabled. The ram was running at 2144 when first booted and that speed was painful. My ddr3 1600mhz felt lightning fast compared to it.

This computer was built specifically to handle Unreal Engine 4, Blender and Creative Cloud workloads and boy does it deliver. Eventually I may upgrade to 128gb ram but I really don't need it right now; it runs perfectly with 2 instances of Unreal open, several chrome tabs, PhotoShop and Blender. 

For benchmarks, I tested Unreal Engine 4, Blender and two of my most demanding games; House Flipper and Planet Coaster.

In Blender, my gtx 980 took 2 minutes 14 seconds to render this final doughnut scene using CUDA. The 3090 did it in 9 seconds with the new optix renderer and 14 seconds using CUDA. Every person I talk to has raised their eyebrows at me for spending £1400 on a graphics card but it's sped up my workflow by 1000%. I have zero regrets.

When it comes to Unreal Engine, my i7-4790k usually took 25 minutes to compile 5000 shaders. The 3950x took 2 minutes. Out of the bag UE4 will try its best to utilise all of the cores you have and when I opened up one of my biggest projects, the editor hung for a good 5 minutes but task manager showed it was using every core to compile shaders. Moving round the scene is buttery smooth and landscape editing is no longer a chore.

Photoshop can still be a bit jittery when doing certain things and I've even got it installed on one of the NVME's but Adobe applications will happily take up all your ram and demand more so I'm not too bothered. I am now running CC 2021 now though which is nice. I stayed at 2017 on Kyoya as he was struggling.

I'm impressed with the CPU cooler; even at 100% load the fans stay around 700-1000rpm with the temperature reaching highs of 42 degrees. The highest I saw it was 49 whilst playing Planet Coaster. That game actually turned out to be a great stress tester as one of my worlds has thousands of items. I stopped playing it on Kyoya a year ago because he just couldn't handle all the objects anymore. The 3090 reached up to 70 but I've noticed that it won't even turn the fan on under 60 degrees. It seems Nvidia have made their new cards run happily at temps of 60/70 degrees.


Playing House Flipper on max settings for the first time in 6 months was glorious though. The 980 was getting dangerously close to 90 degrees with all the latest additions and amount of items you can add (also I don't think this game has been optimised well...if at all). I had to limit the game to 60 fps and keep everything on medium. The 3090 happily sits at 60 degrees with max settings and 120fps. I can finally stick as much shit as I want in houses and not worry about my gpu.

On scenes like this, the 980 really struggled on max settings


My most played game is Minecraft but that can pretty much run on a potato. I did turn RTX on and the 3090 didn't even care.


A quick note on some of the other items:

Noctua Industrial case fans -  When these are running at 3000rpm you'll know about it. They sound like jet engines taking off. I keep them around 400 rpm, ramping up to 1500 when the cpu is at max load but even the lower speeds are more than enough to keep the case cool. Plus they look beautiful.

Fractal Design Define 7 XL - I don't know what made me buy the XL. The standard Define 7 would've been more than enough but it was a joy to build in. It's absolutely huge but looks fantastic. Airflow is great, storage solutions are insane (can hold up 20 drives) and it has a fan control center as you can fit an absurd amount of fans in it.

Fractal Ion 860w PSU - I really wanted at least a 1000 watt psu after watching several videos on the 3090 just to be on the safe side but there were no power supplies with a platinum rating going at the time I was buying. I eventually settled on this one as it was the highest platinum wattage I could find and Fractal offers a 10 year warranty. I'm glad I did. The cables are smart and easy to work with and it runs completely silent. I've had no problems with it and seen the 3090 spike several times with no power outages.

Asus Crosshair VIII Formula - Completely unnecessary but it's beautiful. I love the little oled display; it's well worth the price jump from the Crosshair VIII Hero. I like to have it display the CPU temp but it can display custom gifs. Very easy to build on and the IO shield was already installed. I am extremely happy with this purchase. One little thing; I've been using the same speakers from Philips for 15 years and the sound difference from this PC is astonishing. 

Overall; I'm very happy. Even more so for building it myself (it was my first time!) I'm still keeping an eye out for a 5950x but Archer has already exceeded my expectations for a personal dev PC so I probably won't. 

Wednesday, 17 March 2021

Chapter 20 // Drill 6, 7, 8 - Principles & Practice Using C++

In this exercise I am using Visual Studio Community 2019 and a modified version of the std_lib_facilities header found here.

Drill 6

Write a simple copy() operation,
template<typename Iter1, typename Iter2>
    // requires Input_iterator<iter1>() && Output_iterator<Iter2>()
Iter2 copy(Iter f1, Iter e1, Iter f2);
that  copies [f1, e1) to [f2, f2+(e1-f1)) and returns f2+(e1 - f1) just like the standard library copy function. Note that if f1==e1 the sequence is empty, so that there is nothing to copy.

Drill 7

Use your copy() to copy the array into the vector and to copy the list into the array.

Drill 8

Use the standard library function find() to see if the vector contains the value 3 and print out its position if it does; use find() to see if the list contains the value 27 and print out it's position if it does. The "position" of the first element  is 0, the position of the second element is 1, etc. Note that if find() returns the end of the sequence, the value wasn't found.

Github: 

In drill 7 I realised he meant to use a std:: array as a normal C array does not have iterators built in, so I changed it.

I did discover some nice std functions in these drills though. Namely distance() which returns the index of an iterator and find. I'm sure I've used find before but now I actually understand what it's doing "under the hood".

Tuesday, 16 March 2021

Chapter 20 // Drills 1, 2, 3, 4, 5 - Principles & Practice Using C++

In this exercise I am using Visual Studio Community 2019 and a modified version of the std_lib_facilities header found here.

Drill 1

Define an array of ints with the ten elements { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }.

Drill 2

Define a vector<int> with those ten elements.

Drill 3

Define a list<int> with those ten elements.

Drill 4

Define a second array, vector and list, each initialised as a copy of the first array, vector, and list, respectively.

Drill 5

Increase the value of each element in the array by 2; increase the value of each element in the vector by 3; increase the value of each element in the list by 5.

Github: 

I'm not sure if he meant a user defined array (as seen on pg 748), a std::array or an actual array[]. I went with the last one.

Monday, 8 March 2021

Chapter 19 // Exercise 16 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and a modified version of the std_lib_facilities header found here.

Chapter 19 // Exercise 16

Sometimes, it is desirable that an empty vector be as small as possible. For example, someone might use vector<vector<vector<int>>>  a lot but have most elements vectors empty. Define a vector so that sizeof(vector<int>) == sizeof(int*), that is, so that the vector itself consists only of a pointer to a representation consisting of the elements, the number of elements, and a space pointer.


I was a bit confused at first due to the wording as I thought he meant to have 2 pointers but it could only be the size of 1 pointer. But, after re-reading the question several times realised he meant for the vector representation to hold all three.

I basically reused the vector created in exercises 8 and 9 but took out the allocator and used new and delete instead. This created an entire evening of nightmares. If I didn't understand the difference between copy/move constructors and copy/move assignment before; I sure as hell do now.

I ended up using the crt debug library to track down the exact new that was causing me problems and I realised that my move assignment was not deleting properly. I've left the crt stuff in the code; it's an extremely useful tool.


I also became a pedantic about my vectors. I wanted the original vector to be a fully functional vector in it's own right and the SmallVector to just rely on all of OriginalVector's functions. I think that's what caused me the headache as I tried to separate in my head what was an allocation and what wasn't. 

Ultimately, a frustrating yet extremely rewarding exercise.

When I ran the code a vector<vector<vector<int>>> reported a size of 16 and my SmallVector<SmallVector<SmallVector<int>>> was 4.

And with that, Chapter 19 is finally over. I started it on the 22nd of December and it was beginning to feel like the chapter that would never end. That said I've been doing about 3000 other projects in-between. I really need to focus on this book more.

Sunday, 7 March 2021

Chapter 19 // Exercise 14, 15 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and a modified version of the std_lib_facilities header found here.

Chapter 19 // Exercise 14

Provide a GUI interface and a bit of graphical output to the "Hunt the Wumpus" game from the exercises in Chapter 18. Take the input in an input box and display a map of the part of the cave currently known to the player in a window.

Chapter 19 // Exercise 15

Modify the program from the previous exercise to allow the user to mark rooms based on knowledge and guesses, such as "maybe bats" and "bottomless pit."

Github: 

I was both happy and filled with dread at this exercise as my code had been hackily hard coded to suit a console window environment. I then almost gave up as I realised just how much code relied on _getch() pausing the window. After much drinking, I then remembered state machines are thing and hackily threw together a quick state system that forces the game to wait for presses. I then changed all the couts to a stringstream and pushed that to a new widget called Multiline_Outbox which was created from an Fl_Multiline_Outbox.

For the second part, I quickly added another input box where you can type "13p" or "13b" to mark it with a guess. There is no testing anywhere in this game for incorrect input so, put the right input in.

This is quite possibly some of the worst code I've ever written but I'm glad I didn't skip the exercises. I wanted to make it prettier but I also really want to move onto chapter 20.

Due to the amount of file changes I've uploaded the full project to github as well as the main files.

Chapter 19 // Exercise 14, 15  - Principles & Practice Using C++













Thursday, 4 March 2021

Chapter 19 // Exercise 13 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and a modified version of the std_lib_facilities header found here.

Chapter 19 // Exercise 13

Write a Tracer class where its constructor prints a string and its destructor prints a string. Give the strings as constructor arguments. Use it to see where RAII management objects will do their job (i.e., experiments with Tracers as local objects, member objects, global objects, objects allocated by new, etc.). Then add a copy constructor and a copy assignment so that you can use Tracer objects to see when copying is done.


You won't see the destructor calls for anything except the Tracer allocated by new because the rest are destroyed on return 0.

I did find out how to print line numbers in this exercise though. __LINE__ is a very handy macro. There are several others that you can use to print the file, time etc,.

Tuesday, 2 March 2021

Chapter 19 // Exercise 12 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and a modified version of the std_lib_facilities header found here.

Chapter 19 // Exercise 12

Define a File_handle class with a constructor that takes a string argument (the file name), opens the file in the constructor, and closes it in the destructor.


I'm not sure if he wanted us to use ofstream or ifstream or even the c-style FILE. Or if he wanted us to open a file that already exists or open a new file, or use FILE to guess? I decided to go with the simple option of a file to open that already exists seeing as how FILE has not been introduced.

Monday, 1 March 2021

Chapter 19 // Exercise 11 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and a modified version of the std_lib_facilities header found here.

Chapter 19 // Exercise 11

Design and implement a counted_ptr<T> that is a type that holds a pointer to an object of type T and a pointer to a "use count" (an int) shared by all counted pointers to the same object of type T. The use count should hold the number of counted pointers pointing to a given T

Let the counted_ptr's constructor allocate a T object and use a count on the free store. Let counted_ptr's constructor take an argument to be used as the initial value of the T elements. When the last counted_ptr for a T is destroyed, counted_ptr's destructor should delete the T.

Give the counted_ptr operations that allow us to use it as a pointer. This is an example of a "smart pointer" used to ensure that an object doesn't get destroyed until after its last user has stopped using it. Write a set of test cases for counted_ptr using it as an argument in calls, container elements, etc.


So I think this is basically a shared pointer and it took me a moment to wrap my head around what to do. The main key things are to ensure we're not allocating when copying (or increasing if the pointers are pointing at the same thing) as well as only delete the object and counter once all the other shared pointers have gone out of scope.