master
Miloslav Ciz 1 year ago
parent 1e00167b4a
commit e6206b70f4

@ -10,6 +10,8 @@ The Doom engine was revolutionary and advanced (not only but especially) video g
Doom source code is written in [C89](c.md) and is about 36000 [lines of code](loc.md) long. The original system requirements needed roughly a 30 MHz [CPU](cpu.md) and 4 MB [RAM](ram.md) as a minimum. It had 27 levels (9 of which were shareware), 8 weapons and 10 enemy types.
Doom has a [deterministic](determinism.md) [FPS](fps.md)-independent physics which allows for efficient recording of demos of its gameplay and creating [tool assisted speedruns](tas.md). Such demos can be played back in high quality while being minuscule in size and help us in many other ways, for example for verifying validity of [speedruns](speedrun.md). This is very nice and serves as an example of a well written engine (unlike later engines from the same creators, e.g. those of [Quake](quake.md) games which lacked this feature).
The game only used [fixed point](fixed_point.md), no [float](float.md)!
Doom also has a [deterministic](determinism.md) [FPS](fps.md)-independent physics which allows for efficient recording of demos of its gameplay and creating [tool assisted speedruns](tas.md), i.e. the time step of game simulation is fixed (35 tics per second). Such demos can be played back in high quality while being minuscule in size and help us in many other ways, for example for verifying validity of [speedruns](speedrun.md). This is very nice and serves as an example of a well written engine (unlike later engines from the same creators, e.g. those of [Quake](quake.md) games which lacked this feature).
LOL someone created a Doom system monitor for [Unix](unix.md) systems called [psDooM](psdoom.md) where the monsters in game are the operating system [processes](process.md) and killing the monsters kills the processes.

@ -0,0 +1,5 @@
# Greenwashing
*"For every car you consume we plant a tree."* --[corporations](corporation.md)
TODO

@ -17,7 +17,7 @@ These are mainly for [C](c.md), but may be usable in other languages as well.
- **Learn about [dynamic programming](dynamic_programming.md)**.
- **Avoid branches (ifs)** if you can (remember [ternary operators](ternary_operator.md), loop conditions etc. are branches as well). They break prediction in CPU pipelines and instruction preloading and are often source of great performance losses. Don't forget that you can many times compare and use the result of operations without using any branching (e.g. `x = (y == 5) + 1;` instead of `x = (y == 5) ? 2 : 1;`).
- **Use iteration instead of [recursion](recursion.md)** if possible (calling a function costs something).
- **You can use good-enough [approximations](approximation.md) instead of completely accurate calculations**, e.g. taxicab distance instead of Euclidean distance, and gain speed or memory without trading. Nice examples can be found in [computer graphics](graphics.md), e.g. some [software renderers](sw_rendering.md) use perspective-correct texturing only for large near triangles and cheaper affine texturing for other triangles, which mostly looks OK.
- **Use [good enough](good_enough.md) [approximations](approximation.md) instead of completely accurate calculations**, e.g. taxicab distance instead of Euclidean distance, capsule shape to represent the player's collision shape rather than the 3D model's mesh etc. With a physics engine instead of running the simulation at the same FPS as rendering, you may just run it at half and [interpolate](interpolation.md) between two physics states at every other frame. Nice examples can also be found in [computer graphics](graphics.md), e.g. some [software renderers](sw_rendering.md) use perspective-correct texturing only for large near triangles and cheaper affine texturing for other triangles, which mostly looks OK.
- **Use quick opt-out conditions**: many times before performing some expensive calculation you can quickly check whether it's even worth performing it and potentially skip it. For example in physics [collision detections](collision_detection.md) you may first quickly check whether the bounding spheres of the bodies collide before running an expensive precise collision detection -- if bounding spheres of objects don't collide, it is not possible for the bodies to collide and so we can skip further collision detection.
- **Operations on static data can be accelerated with accelerating structures** ([look-up tables](lut.md) for functions, [indices](indexing.md) for database lookups, spatial grids for collision checking, various [trees](tree.md) ...).
- **Use powers of 2** (1, 2, 4, 8, 16, 32, ...) whenever possible, this is efficient thanks to computers working in [binary](binary.md). Not only may this help nice utilization and alignment of memory, but mainly multiplication and division can be optimized by the compiler to mere bit shifts which is a tremendous speedup.
@ -34,13 +34,14 @@ These are mainly for [C](c.md), but may be usable in other languages as well.
- **[Early branching](early_branching.md) can create a speed up** (instead of branching inside the loop create two versions of the loop and branch in front of them). This is a kind of space-time tradeoff.
- **Division can be replaced by multiplication by [reciprocal](reciprocal.md)**, i.e. *x / y = x * 1/y*. The point is that multiplication is usually faster than division. This may not help us when performing a single division by variable value (as we still have to divide 1 by *y*) but it does help when we need to divide many numbers by the same variable number OR when we know the divisor at compile time; we save time by precomputing the reciprocal before a loop or at compile time. Of course this can also easily be done with [fixed point](fixed_point.md) and integers!
- **Reuse variables to save space**. A warning about this one: readability may suffer, mainstreamers will tell you you're going against "good practice", and some compilers may do this automatically anyway. Be sure to at least make this clear in your comments. Anyway, on a lower level and/or with dumber compilers you can just reuse variables that you used for something else rather than creating a new variable that takes additional RAM; of course a prerequisite for "merging" variables is that the variables aren't used at the same time.
- **To save memory use [compression](compression.md) techniques.** Compression doesn't always have to mean you use a typical compression algorithm such as [jpeg](jpg.md) or [LZ77](lz77.md), you may simply just throw in a few compression techniques such as [run length](run_length.md) or word dictionaries into your data structures. E.g. in [Anarch](anarch.md) maps are kept small by consisting of a small dictionary of tile definitions and map cells referring to this dictionary (which makes the cells much smaller than if each one held a complete tile definition).
- **What's fast on one platform may be slow on another**. This depends on the instruction set as well as on compiler, operating system, available hardware, [driver](driver.md) implementation and other details. In the end you always need to test on the specific platform to be sure about how fast it will run. A good approach is to optimize for the weakest platform you want to support -- if it runs fasts on a weak platform, a "better" platform will most likely still run it fast.
- **Mental calculation tricks**, e.g. multiplying by one less or more than a power of two is equal to multiplying by power of two and subtracting/adding once, for example *x * 7 = x * 8 - x*; the latter may be faster as a multiplication by power of two (bit shift) and addition/subtraction may be faster than single multiplication, especially on some primitive platform without hardware multiplication. However this needs to be tested on the specific platform. Smart compilers perform these optimizations automatically, but not every compiler is high level and smart.
- **Else should be the less likely branch**, try to make if conditions so that the if branch is the one with higher probability of being executed -- this can help branch prediction.
- Similarly **order if-sequences and switch cases from most probable**: If you have a sequences of ifs such as `if (x) ... else if (y) ... else if (z) ...`, make it so that the most likely condition to hold gets checked first, then second most likely etc. Compiler most likely can't know the probabilities of the conditions so it can't automatically help with this. Do the same with the `switch` statement -- even though switch typically gets compiled to a table of jump addresses, in which case order of the cases doesn't matter, it may also get compiled in a way similar to the if sequence (e.g. as part of size optimization if the cases are sparse) and then it may matter again.
- **You can save space by "squeezing" variables** -- this is a space-time tradeoff, it's a no brainer but nubs may be unaware of it -- for example you may store 2 4bit values in a single `char` variable (8bit data type), one in the lower 4bits, one in the higher 4bits (use bit shifts etc.). So instead of 16 memory-aligned booleans you may create one `int` and use its individual bits for each boolean value. This is useful in environments with extremely limited RAM such as 8bit Arduinos.
- **You can optimize critical parts of code in [assembly](assembly.md)**, i.e. manually write the assembly code that takes most of the running time of the program, with as few and as inexpensive instructions as possible (but beware, popular compilers are very smart and it's often hard to beat them). But note that such code loses [portability](portability.md)! So ALWAYS have a C (or whatever language you are using) [fallback](fallback.md) code for other platforms, use [ifdefs](ifdef.md) to switch to the fallback version on platforms running on different assembly languages.
- **Loop unrolling/splitting/fusion, function inlining etc.**: there are optimizations that are usually done at [assembly](assembly.md) level (e.g. loop unrolling physically replaces a loop by repeated commands which gains speed but also makes the program bigger) and higher level languages try to perform them automatically. However if you're writing in assembly or have a dumb compiler (or are even writing a compiler) you may do these automatically, e.g. with macros/templates etc. Sometimes you can hint a compiler to perform these optimizations, so look this up.
- **Loop unrolling/splitting/fusion, function inlining etc.**: there are optimizations that are usually done by high level languages at [assembly](assembly.md) level (e.g. loop unrolling physically replaces a loop by repeated commands which gains speed but also makes the program bigger). However if you're writing in assembly or have a dumb compiler (or are even writing your own) you may do these manually, e.g. with macros/templates etc. Sometimes you can hint a compiler to perform these optimizations, so look this up.
- **[Parallelism](parallelism.md) ([multithreading](multithreading.md), [compute shaders](compute_shader.md), ...) can astronomically accelerate many programs**, it is one of the most effective techniques of speeding up programs -- we can simply perform several computations at once and save a lot of time -- but there are a few notes. Firstly not all problems can be parallelized, some problem are sequential in nature, even though most problems can probably be parallelized to some degree. Secondly it is hard to do, opens the door for many new types of bugs, requires hardware support (software simulated parallelism can't work here of course) and introduces [dependencies](dependency.md); in other words it is huge [bloat](bloat.md), we don't recommend parallelization unless a very, very good reason is given. Optional use of [SIMD](simd.md) instructions can be a reasonable midway to going full parallel computation.
- **Specialized hardware (e.g. a [GPU](gpu.md)) astronomically accelerates programs**, but as with the previous point, portablity and simplicity greatly suffers, your program becomes bloated and gains dependencies, always consider using specialized hardware and offer software fallbacks.

@ -2,7 +2,7 @@
*Not to be confused with [science](science.md).*
Soyence is a cult of [propaganda](propaganda.md), [politics](politics.md), [business](business.md), [bloat](bloat.md) and [bullshit](bullshit.md) trying to pass as [science](science.md), nowadays promoted typically by [pseudoleftist](pseudoleft.md) [soyboys](soyboy.md) and [pseudoskeptics](pseudoskepticism.md). It is what the typical reddit [atheist](atheism.md) or [tiktok](tiktok.md) [feminist](feminism.md) believes is science or what Neil De Grass Tyson tells you science is. Soyence calls itself science and [gatekeeps](gatekeeping.md) the term science by calling unpopular science -- such as that regarding human [race](race.md) or questioning big pharma [vaccines](vaccine.md) -- "[pseudoscience](pseudoscience.md)". Soyence itself is pseudoscience but it has the added attributes of pursuing [evil](evil.md) and trying to hide among serious science.
Soyence is a cult of [propaganda](propaganda.md), [politics](politics.md) and other kinds of [business](business.md) trying to pass as [science](science.md), nowadays promoted typically by [pseudoleftists](pseudoleft.md) and [pseudoskeptics](pseudoskepticism.md). Soyence is not about listening to what science says, it is about listetning what scientists say (or rather those who were officially pronounced "scientists"); soyence is what the typical reddit [atheist](atheism.md) or [tiktok](tiktok.md) [feminist](feminism.md) believes is science or what Neil De Grass Tyson tells you science is. Soyence calls itself science and [gatekeeps](gatekeeping.md) the term science by calling unpopular science (such as that regarding human [race](race.md) or questioning big pharma [vaccines](vaccine.md)) "[pseudoscience](pseudoscience.md)". Soyence itself is pseudoscience but it has the added attributes of intentional misleading, mainstream popularity, state approval etc.
Compared to good old [fun](fun.mf) pseudosciences such as [astrology](astrology.md), soyence is extra sneaky by purposefully trying to blend in with real science, i.e. within a certain truly scientific field, such as biology, there is a soyentific [cancer](cancer.md) mixed in by activists, corporations and state, that may be hard to separate for common folk and many times even for pros. This is extremely [harmful](harmful.md) as in the eyes of retarded people (i.e. basically everyone) the neighboring legit science gives credibility to propaganda bullshit. There is a tendency to think we somehow magically live in a time that's fundamentally different from other times in history in which it is now a pretty clear and uncontroversial fact that the name of science was abused hard by propaganda, almost everyone easily accepts that historically politically constructed lies were presented as confirmed by science, but somehow people refuse to believe it could be the case nowadays. In times of Nazism there was no doubt about race being a completely scientific term and that Jews were scientifically confirmed to be the inferior race -- nowadays in times when anti Nazis have won and politics is based on denying existence of race somehow scientists start to magically find evidence that no such thing as race has ever existed -- how convenient! And just in case you wanted to check if it's actually true, you'll be labeled a racist and you won't find job ever again.

Loading…
Cancel
Save