devbug
Joined 14 years ago
Joined 14 years ago
We’re now using Python for training and forking Ortex (ONNX) for inference.
The ecosystem just isn’t there, especially for training. It’s a little better for inference but still has significant gaps. I will eventually have time to push contributions upstream but Python has so much momentum behind it.
Livebooks are amazing though and a better experience than anything a Python offers sans libraries.
ROMED8U-2T
Do you know if Telkom offered ISDN around ‘95 thru to ‘01?
My parents had “two lines” back then so we could always have access to the Internet, even while talking on the phone. I recall, vaguely, using dial up but we may have had an ISDN line. In part, because my Dad wanted to order LaserDiscs from the US while my Mom was chatting away to family.
[1]: https://www.postgresql.org/docs/current/logical-replication....
To give a slightly more detailed description, you allocate two arrays of the extents. One is the dense array of whatever type, say T, and the other is the sparse array of 32 bit or 64 bit integers. The sparse array stores indices into the dense array for extant objects. However, for extinct objects, the indices instead point to the sparse array itself to encode a free-list.
To insert, in O(1), you check the free-list for an unused slot. If there is none, then you grow the sparse array (increment a counter) and use the newly introduced slot. Then you insert (or construct in place) your object at the end of the dense array. Finally, you map that slot in the sparse array to the end of the dense array.
To delete, in O(1), you swap the object you wish to delete with the last in the dense array and decrement the counter (swap and pop). Then you add the index in the sparse array to the free-list. You’ll need to know the index assigned to the object you swapped with to do this, which can either be stored on the object itself or by introducing another array the maintains an inverse mapping.
To iterate, you can treat the dense array like any other array.
This scheme poses some challenges:
- You lose pointer stability because you are relocating your objects. You must access them through indices. If you can defer your deletions, say to a frame boundary, you assume your pointers are stable.
- Indices, without further work, are not safe. They are just as safe as pointers. Usually you don’t expect more than N objects, so you can use log2(N) bits for the forward and reverse mappings between sparse and dense arrays and then use the leftover bits to identify stale indices. You can, and should, encapsulate this in a type-safe handle system. [2][3]
- High churn can cause index invalidation to fail (if you wrap a counter) and performs worse than other data structures.
- “Swap and pop” requires T to be trivially copyable, or ideally, trivially relocatable.
It’s also worth mentioning that you can reorder the dense array to maintain custom invariants. This is really useful if you have dependencies between objects and want to iterate in order.[4]
[1]: http://bitsquid.blogspot.com/2014/08/building-data-oriented-...
[2]: https://floooh.github.io/2018/06/17/handles-vs-pointers.html
[3]: You usually can use 24 bits for index and 8 bits for a discriminator (counter) in games. Handles (that you pass around) can be wider to exploit register widths and increase safety, since you have 32 bits for further runtime checks.
[4]: By doing more work at insertion and deletion, a constant factor on O(1), you can save work on iteration or updates, a constant factor on O(n). A great example of this being a worthwhile optimization is for scene graphs or transform hierarchies. If you partially order by depth in the hierarchy, you can guarantee correct computation without chasing indexes or pointers. If you maintain additional information about boundaries, you can trivially parallelize computation of transforms or reduce redundant work.
Neat that the committee is looking to introduce it. Too bad we eschew the STL (and even CRT) in games.
It's frequently used in Entity-Component Systems (ECS) which introduce safety by associating a counter with each entry in the sparse array (usually called a "generation") and incrementing them on deletion. You can also verify cross-linkage between the sparse and dense arrays like the data structure described in the article, but that comes at the cost of another indirection and fetch from memory.
I’m glad to see the open source development of these tools. Personally, there’s a lot of stuff colleagues and I have built that I would love to see open sourced. Otherwise we just end up implementing the same services over and over again.
Another example is patch delivery. It’s a solved problem yet everyone keeps rolling their own, or only shipping to Steam. Of course, all managed with some Jenkins scripts written by someone that’s no longer at the company. I want Fastlane for games that makes it easy to target the various distribution channels across desktop/mobile/console.
I've been meaning to implement SGP4 from scratch as a learning exercise. What I found really interesting is how the USAF/NORAD tracks and reports objects in LEO: they publish Two-line Element Sets (TLEs), which are a fixed-width ASCII format derived from punch cards.[1] The format is pretty easy to parse.[2]
[1]: https://en.wikipedia.org/wiki/Two-line_element_set [2]: https://www.celestrak.com/NORAD/documentation/tle-fmt.php [3]: https://www.celestrak.com/NORAD/documentation/checksum.php
https://www.scalyr.com/blog/searching-1tb-sec-systems-engine...
These provided MFTs have to meet certain minimum requirements for certification by Microsoft, which amounts to "good enough." Results vary in practice and can be incredibly frustrating (especially encode). It's often better to use the underlying SDKs but that comes with a lot of hassle.
(I've been working on a video capture and sharing app inspired by Shadowplay.)
Windows 10 is also rolling out support for AV1, though not bundled.[4]
[1]: https://docs.microsoft.com/en-us/windows/win32/medfound/h-26...
[2]: https://docs.microsoft.com/en-us/windows/win32/medfound/abou...
[3]: https://chromium.googlesource.com/chromium/src/+/master/medi...
[4]: https://www.microsoft.com/en-us/p/av1-video-extension/9mvzqv...
I've done it, not out of performance concerns, but because transcoding between proprietary binary formats with types is a lot saner than the alternative.
[1]: https://www.postgresql.org/docs/current/sql-copy.html#id-1.9...
I did this manually back in Feb 2024[1], but only got "connector A" mapped out and a partially designed SXM2-to-PCIe interposer designed before getting distracted.
During the process, I discovered Facebook's Big Basin JBOG schematics/specs (from Open Compute), which contained a design derived from NVIDIA's DGX-1 reference implementation. Looks like this clears up some gaps in the current reference. It also explains some of the design choices, like the form factor and similar pinout to OpenPOWER.
https://docs.google.com/spreadsheets/d/1DfH0T9KWWoc2CpKZsRIT...