rdw
Joined 15 years ago
Joined 15 years ago
This means their strategy is more like:
1. If someone builds a market-leading unsafe strong AI, it may be misused in a damaging way by a large number of humans, undermining society and creating a catastrophic upheaval.
2. However, if the leading AI maker also works to make it safe against misuse, as long as the stay in the lead and keep it safe, then the ability of human bad actors to misuse the AI is limited. Given enough time, society will adapt to pretty much anything, so eventually there's no longer an arms race to stay ahead.
I don't really know whether I agree with their concerns, but I do think that (my understanding of) their principles is that they're reasonable, self-consistent, and they adhere to them in all their public and private actions.
You can't always choose to write straight code. What you're trying to do may require IO, and then that introduces concurrency, and the need for mutual exclusion or notification.
Examples: If there's a read-through cache, the cache needs some sort of lock inside of it. An async webserver might have a message queue.
The converse is also true. I've been writing some multithreaded code recently, and I don't want to or need to deal with mutexes, so, I use other patterns instead, like thread locals.
Now, for sure the async equivalents look and behave a lot better than the threaded ones. The Promise static methods (any, all, race, etc) are particularly useful. But, you could implement that for threads. I believe that this convenience difference is more due to modernity, of the threading model being, what 40, 50, 60 years old, and given a clean-ish slate to build a new model, modern language designers did better.
But it raises the idea: if we rethought OS-level preemptible concurrency today (don't call it threads!), could we modernize it and do better even than async?
I kind of like this analogy because it does help us reason about the situation. The one-room shack is basically an MVP; a hacky result that just does one thing and probably poorly, but it is useful enough to justify its own existence. The giant mansion built from detailed architectural plans seems like a waterfall process for an enterprise application, doesn't it?
There are many advantages to building a house one room at a time. You get something to house you quickly and cheaply. When you build each extension, you have a very good idea of how it will be most useful because you know your needs well. You are more capable of taking advantage of sales (my neighbor collects construction overstock for free/cheap and starts building something once he has enough quantity to do so). It's more "agile". The resulting houses are beautiful in their own bespoke ways. They last a long time, too.
The downsides are that the services and structure are a hodgepodge of eras and necessity. If you're competent, you can avoid problems in your own work, but you may have to build on shoddy "legacy" work. You spend more of your time in a state of construction, and it may be infeasible to undertake a whole-house project like running ethernet to every room.
It's all tradeoffs. I think it does in many cases make sense to build a house in this way, and it likewise makes sense to build software this way. It depends on the situation.
So, the bitter lesson is based on a disappointment that you're building intelligence without understanding why it works.
Most game engines are written as a large chunk of C++ code that runs each frame's timing, and the big subsystems like physics, particles, sound, and the scenegraph. All the important engineers will be dedicated to working on this engine and it behaves like a framework. The "game logic" is generally considered to be a minority of the code, and because less-technical people generally author it, it gets written in a higher-level "scripting" language.
This creates some serious constraints on that language. It must be possible to call into the scripts from the main engine and the overhead must be low. The scripts often have to make calls into the data structures of the main engine (e.g. for physics queries) and the overhead of that should be low as well. It should also be possible to control the scripting language's GC because the main engine is pretty timing-sensitive. Memory consumption is pretty important as well.
All these requirements point towards two implementations specifically: Lua (and LuaJIT), and Mono. Those two runtimes go out of their way to make it easy and fast to embed. A third option which a lot of engines pick is to write their own scripting language where they control everything about it. Any other language you can think of (with the possible exceptions of Haxe) will have some major hurdle that prevents easy embedding. The fact that you can compile multiple languages to Mono bytecode pushes some folks in that direction; if you're planning to write a lot of code in the scripting engine (not all of them do! See: Unreal) that's nice flexibility to have.
The 11" Air I got to replace the Eee was much better in every single way. One note is that the thin-and-long of the Air was much more portable than the chunky but stubbier Eee. It just fits better into the kinds of bags we all have. The thinness wars started then.