7 ms·
Steel Bank Common Lisp version 2.6.7
- arikrahman 2mo agoGreat semver number
- wk_end 2mo ago* the SB-SIMD contrib now supports ARM64. (Thanks to Sylvia Harrington) * AVX512 instructions are now supported on X86-64. (Thanks to Robert Smith and Arthur Miller) * additional support for SIMD instructions on ARM64 and X86-64. (Thanks to Arthur Miller) These seem like pretty awesome additions. Does anyone know how SIMD works in SBCL? Is this at the codegen layer? i.e. can it auto-vectorize or anything like that? Or are these intrinsics you have to explicitly ask for?
- wild_egg 2mo agoNo auto-vectorization yet, but you may find this illuminating: https://www.stylewarning.com/posts/nbody https://www.stylewarning.com/posts/nbody
- BoingBoomTschak 2mo agoAnd the very recent https://old.reddit.com/r/lisp/comments/1v6kyyn/so_they_say_lisp_is_slow/ https://old.reddit.com/r/lisp/comments/1v6kyyn/so_they_say_l...
- e12e 2mo agoLooks like you use it explicitly? https://github.com/sbcl/sbcl/tree/master/contrib/sb-simd https://github.com/sbcl/sbcl/tree/master/contrib/sb-simd
- peri-cl 2mo ago> "AVX512 instructions are now supported on X86-64" This is the first news I've seen on HN in weeks that I am genuinely excited about! I have several AVX-2 hobby projects in Common Lisp, and an AVX-512 machine. It's an unexpected surprise to read this morning that this very useful ISA is suddenly unlocked. I'll be trying it out right away. (edit: Looks like they mean *compiler* support for AVX-512, but not SB-SIMD definitions (yet). So I believe the only way for end-users to call AVX-512 instructions right now is to write custom VOP's). > "Or are these intrinsics you have to explicitly ask for?" There are language SIMD types and you explicitly use SIMD functions that operate on them. I believe it's essentially the same idea as C intrinsics. You can for example write (interactively) (u32.8+ (make-u32.8 0 1 2 3 4 5 6 7) (u32.8 10)) ;; => #<SB-EXT:SIMD-PACK-256 10 11 12 13 14 15 16 17> And that's VPADDD under the hood. Or reading an array (loop with sum = (f32.8 0.0f0) for index below (* 8 (floor length 8)) by 8 do (setq sum (f32.8+ (f32.8-aref array index) sum)) finally (return sum)) which compiles down to a small loop around the vector insts VMOVUPS YMM1, [RDX+RCX*2+1] VADDPS YMM0, YMM1, YMM0 I much prefer it to writing intrinsics in C (and the results are just as good). It's an interactive, exploratory, coding: I write small modular functions, SBCL compiles them on the fly, I glue them together with high-level language constructs.
- Archit3ch 2mo ago> I much prefer it to writing intrinsics in C (and the results are just as good). It's an interactive, exploratory, coding: I write small modular functions, SBCL compiles them on the fly, I glue them together with high-level language constructs. Same here, but in Julia instead. Sometimes I drop down to LLVM intrinsics (e.g. to force lop3.lut on GPUs).
- amno 2mo ago> This is the first news I've seen on HN in weeks that I am genuinely excited about! I have several AVX-2 hobby projects in Common Lisp, and an AVX-512 machine. It's an unexpected surprise to read this morning that this very useful ISA is suddenly unlocked. I'll be trying it out right away. Nice to hear! :) It is the basic compiler support, and lots of instructions added. However, you can't use knor, knoq and similar since they require scheduling of k-masks. Not done yet. But you can certainly use some of avx512 instructions and add yourself if you need some that is not available already. Check https://github.com/sbcl/sbcl/blob/master/src/compiler/x86-64/avx512-insts.lisp https://github.com/sbcl/sbcl/blob/master/src/compiler/x86-64....
- amno 2mo ago> Is this at the codegen layer? On implementation level, it is a codegen layer. It uses a system of macros to generate instructions from a database of instructions. The database is specified manually: https://github.com/sbcl/sbcl/tree/master/contrib/sb-simd/code/instruction-sets https://github.com/sbcl/sbcl/tree/master/contrib/sb-simd/cod... At compile-time, they are converted into "VOPs", i.e. intrinsic functions, which are used by the compiler to emit the actual machine instructions. > can it auto-vectorize or anything like that? Unfortunately, it can't. > are these intrinsics you have to explicitly ask for? Yes, more like higher-level intrinsics. You get quite some automation, but you are requesting manually what you need. More like a DSL, than pure intrinsics. This is how you can use it (as an example): (defun count-lines-and-words-ascii (sap size ws-init-state) (declare (type fixnum size) (type (unsigned-byte 8) ws-init-state) (type sb-sys:system-area-pointer sap) (optimize (speed 3) (safety 0))) (loop with loop-end of-type fixnum = (logandc2 size 127) for i of-type fixnum from 0 below loop-end by 128 with 0x0 of-type u8.32 = (u8.32 #x00) with 0x20 of-type u8.32 = (u8.32 #x20) with 0x0A of-type u8.32 = (u8.32 #x0A) with wa of-type u64.4 = (u64.4 0) with la of-type u64.4 = (u64.4 0) with ws-prev of-type u8.32 = (u8.32 ws-init-state) for c1 = (u8.32-sap-ref sap (+ i 0)) for c2 = (u8.32-sap-ref sap (+ i 32)) for c3 = (u8.32-sap-ref sap (+ i 64)) for c4 = (u8.32-sap-ref sap (+ i 96)) do (flet ((process-chunk (curr prev) (let* ((ctrl (u8.32-sat- (u8.32- curr 9) 4)) (ws (u8.32-or (u8.32= ctrl 0x0) (u8.32= curr 0x20))) (ws-shift (u8.32-alignr ws (u8.32-permute128 prev ws #x21) 15)) (wmask (u8.32-andc1 ws ws-shift)) (lmask (u8.32= curr 0x0A))) (values wmask lmask ws)))) (multiple-value-bind (wm lm prev) (process-chunk c1 ws-prev) (psetf wa (u64.4+ wa (u8.32-sad wm 0x0)) la (u64.4+ la (u8.32-sad lm 0x0)) ws-prev prev)) (multiple-value-bind (wm lm prev) (process-chunk c2 ws-prev) (psetf wa (u64.4+ wa (u8.32-sad wm 0x0)) la (u64.4+ la (u8.32-sad lm 0x0)) ws-prev prev)) (multiple-value-bind (wm lm prev) (process-chunk c3 ws-prev) (psetf wa (u64.4+ wa (u8.32-sad wm 0x0)) la (u64.4+ la (u8.32-sad lm 0x0)) ws-prev prev)) (multiple-value-bind (wm lm prev) (process-chunk c4 ws-prev) (psetf wa (u64.4+ wa (u8.32-sad wm 0x0)) la (u64.4+ la (u8.32-sad lm 0x0)) ws-prev prev))) finally (return (loop for j from loop-end below size with words of-type fixnum = (sum-lanes wa) with lines of-type fixnum = (sum-lanes la) with prev-ws of-type boolean = (logbitp 31 (u8.32-movemask ws-prev)) with tlines of-type fixnum = 0 with twords of-type fixnum = 0 for byte of-type fixnum = (sb-sys:sap-ref-8 sap j) for curr-ws of-type boolean = (or (= byte 32) (<= 9 byte 13)) do (when (= byte 10) (incf tlines)) (when (and (not curr-ws) prev-ws) (incf twords)) (setf prev-ws curr-ws) finally (return (values (the fixnum (+ lines tlines)) (the fixnum (+ words twords)) nil))))))
- NeutralForest 2mo agoGreat to see the project is still going strong, I kinda want to try CL but I always feel like I don't have a great use-case.
- GalaxyNova 2mo agoCL can be used pretty much anywhere nowadays, even on the web with ECL wasm compilation.
- NeutralForest 2mo agoI have a todo list longer than the Tour de France I want to tackle first!
- ivxvm 2mo agoAnywhere is where exactly? I've been thinking of where I could use it for like 10 minutes, and I couldn't come up with anything. Maybe a game engine or web services. It wouldn't make much sense for any kind of desktop software or command line utilities that are supposed to start really fast and have minimal runtime.
- ux266478 2mo agoA binary has a startup time of like 20 milliseconds, the overwhelming majority of that is setting up page tables iirc. While that's a lot for a small cli utility called in a loop, it's really nothing for a desktop application. I wish more desktop applications could hit even a 100ms startup time. These days it feels like 5 seconds or more is the norm.
- deleted 2mo ago[deleted]
- klibertp 2mo agoOn the contrary, CLI, TUI, and desktop GUI apps are basically the only kinds of apps that benefit from CL and can live with its shortcomings. The startup time of a tool written in CL is short: you just need to load the image into RAM, run some hooks (if configured), and you're good to go. If you don't include loads of dependencies, the dumped image is also not too big, so loading it from an SSD is almost instantaneous. The startup is of course nowhere near that of a small C or Zig binary, but for larger tools it will be tolerable. For TUIs and GUIs, you can work on them interactively and see the changes in the source immediately reflected in the interface of a running instance. Web services need either cooperative concurrency or M:N concurrency due to the "10k problem". CL only supports threads (OS-level) and promises; everything else is incomplete (eg., delimited continuations, which could be used to build coroutines) due to missing parts in the spec and some language features (eg., conditions and restarts). Of course it can be done, but it won't be as pleasant as using Elixir and Phoenix. A game engine would work, most likely, unless it was for an MMO (again, concurrency handling). I personally never worked on one, but I see examples of game engines in CL, and they tend to look nice. In general, single-user desktop (CLI, TUI, GUI) apps are still a good fit for CL, even today (you need to put some work into packaging the app for different platforms, but it tends to be easier to set up than it is for C or C++; harder than Go or Rust, though). It's unfortunately not as good a fit for the backend, at least not until an implementation with good support for concurrency appears. It's nice as an extension language in a larger app (through ECL), and as far as dynamic languages go, it's quite performant, so some computation-heavy apps can benefit from using CL (with SBCL). On the other hand, the ecosystem is quite small, which means dependency-heavy apps are better written in something like Python or a mixture of CL and another language (there are two-way bindings to many dynamic languages and there's mature FFI support for compiled languages). To be perfectly honest: as much as I love Lisp, I personally gave up on trying to use it, for now. For hobby stuff, I found an even more niche solution that is more enjoyable to work with in the GUI/TUI/CLI space. It also doesn't support OS-level threads, but instead provides coroutines for concurrency - I find this side of the trade-off to be useful/beneficial more often, at least in the code I tend to write. I don't believe the time spent learning CL and other Lisps was wasted, but it's become harder and harder to justify going for CL over the past 15 years, and I finally reached a point where I stopped trying. YMMV though, and I would still give CL a chance if it's your first language of this kind (i.e., providing image-based interactive development, a dynamic language with a native compiler with inline assembly support, a multimethod-based object system, and homoiconicity/macros, etc.).
- sroerick 2mo agoI'm going pretty deep on Lisp on accident - can anybody give me more context on this?
- wild_egg 2mo agomore context beyond the changelog? what would you like to know?
- hermitShell 2mo agoYou might find this interesting: https://news.ycombinator.com/item?id=43636230 https://news.ycombinator.com/item?id=43636230
- DonHopkins 2mo ago(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
- dapperdrake 2mo ago#|))))
- WalterGR 2mo agoThat’s Scheme, not Common Lisp. I’d recommend using close parens for your code sample. Those are portable between the two.
- tmtvl 2mo agoIn Common Lisp it'd be: (funcall (funcall (funcall (funcall ; ... ...though I don't think that functions which return functions which return functions which return functions ad infinitum are a great idea. Simply taking a value and returning a value means you can use a pipelining operator: (~> some-data function-1 function-2 (function-3 _ some-other-data) ; ... function-n)
- vindarel 2mo agoUse `C-c C-]` (`slime-close-all-parens-in-sexp`) in SLIME ;)
- HexDecOctBin 2mo agoIf any SBCL dev is here, please add documentation for how to use the memory arena feature. The only doc is an very old proposal document.
- stackghost 2mo agoYeah I'm not sure why it's not in the manual, as it's had arena allocation support since at least 2.4.x, but basically: - use SB-VM:NEW-ARENA to make a new arena - use SB-VM:WITH-ARENA to redirect ordinary allocation into an existing arena like you would use WITH-OPEN-FILE or similar macros The only real doc is this internals note, and it doesn't even cover NEW-ARENA which I guess is left as an exercise to the reader: https://github.com/sbcl/sbcl/blob/master/doc/internals-notes/arena-allocation.txt https://github.com/sbcl/sbcl/blob/master/doc/internals-notes...
- HexDecOctBin 2mo agoYeah, but I am guessing one needs a bit more info on how this works together with GC. For example, once an arena goes out of scope, what happens to allocations made inside it that have been returned and thus are referred to from outside that scope? Are they copied out or do we have a dangling pointer? Stuff like this needs some decent documentation in order to be able to use a low level feature like this properly.
- Jach 2mo agoIndeed. The behavior of arenas shared by multiple threads is important as well, and the proper use of destroy-arena vs. rewind-arena. Without care it's easy to create a leak in the unmanaged memory and the OOM Killer will come for your process eventually.
- baq 2mo agoI wonder sometimes how the world would look like if lisp won and the unit of deployment was a lisp machine image, if that makes sense. How would a kubernetes optimized for lisp look like? How would AWS EC2 look like? etc.
- tyromaniac 2mo agoWe wouldn't have need such barbaric things in a lisp world. :p Personally I think/hope they would have earlier discoveries / more broad usage of the deterministic systems like nix etc, which are built upon functional principles of immutability etc. Maybe the world would be guix/Hurd!
- neutronicus 2mo ago> Personally I think/hope they would have earlier discoveries / more broad usage of the deterministic systems like nix etc, which are built upon functional principles of immutability etc. Yeah, that, uh, doesn't sound like Lisp
- tyromaniac 2mo agohttps://guix.gnu.org/ https://guix.gnu.org/
- neutronicus 2mo agoYeah, I mean, I know it exists, but the mythology of Lisp is built around "I can drop into a REPL and execute arbitrary code on a production system and that is a good thing"
- tyromaniac 2mo agoAs opposed to our wonderful world where everyone does the same with unchecked binaries or obfuscated/minified JS? To me the mythology of lisp (from my mostly outsider perspective) is more like "make everything a interoperable DSL" (although if this is what you were describing with your sentence then thats fair enough)
- WalterGR 2mo agoIf memory serves, traditionally, CCL (Clozure Common Lisp [0]) had better support for Windows but SBCL was unbeatable for speed. Is that still the case? [0] https://ccl.clozure.com/ https://ccl.clozure.com/
- jorams 2mo agoSBCL works fine on Windows. It used to display a warning about fragility at startup, but that was removed in version 2.0.3, 6 years ago, after already being obsolete for quite a while. CCL isn't very actively maintained and currently doesn't have an ARM64 port, but otherwise continues to work fine. I believe one reason people use it is that it compiles a bit faster than SBCL, at least in part by doing less optimization.
- pfdietz 2mo agoUsing two implementations also helps identify portability issues coming from places the standard doesn't specify behavior sufficiently.
- GalaxyNova 2mo agoBut CCL is very stable and works very well on the platforms it supports, sometimes in a much more compliant way than SBCL.
- p_l 2mo agoPart of why SBCL took longer is, IIRC, that SBCL went with embedding proper SEH support into generated code (important among other things to get page fault information), whereas CCL used VEH (which is simpler to use but only available from XP onwards)
- taolson 2mo agoFun fact I learned from a Func Prog podcast: the name Steel Bank is a play on it's origin as Carnegie-Mellon Common Lisp (Carnegie made his fortune in Steel, while Mellon did so with Banks): https://www.sbcl.org/history.html https://www.sbcl.org/history.html
- p_l 2mo agoThere's another wordplay in the name. Namely, that "SB" stands for "Sanely Bootstrappable" - something that the CMU Common Lisp was unable to do
- jojohohanon 2mo agoIn my first job, grumpy Martin had as one of his many indispensable tasks, to build cmucl. (Itasoftware, one of the main lisp shops of the age)
- guenthert 2mo agoIt is my understanding that easing bootstrap was the original motivation of the fork of CMU CL. I'm a bit confused about that, since CMU CL supports compilation to byte-code (which should make a port to a new architecture comparatively easy), a feature which was dropped in SBCL.
- p_l 2mo agoThe sane bootstrap is not about porting to new architecture, but about building the compiler from source in the first place. CMU CL effectively requires that you use the same version of CMU CL to build it, IIRC, which in practice meant you had to first load the changes into older CMU CL image - overwriting core components, and then use that image to compile new version. The difference with SBCL is that it can compile so long as you have any CL implementation that handles certain broad, but not complete, subset of ANSI CL. It does it by being able to compile itself in sort-of sandboxed state hosted within another CL image, and then using that compiler to build itself, without requiring to modify the host compiler like CMU As for the bytecode, as far as I recall CMU CL did not have bytecode compiler at all - it had evaluator option, which was indeed dropped for a long time from SBCL but was recently reintroduced, partially to support efforts such as porting Kandria [1] to Nintendo Switch [1] https://kandria.com/ https://kandria.com/
- OuterVale 2mo agoSteel Bank Common Lisp is what Hacker News uses. https://news.ycombinator.com/item?id=44099006 https://news.ycombinator.com/item?id=44099006 I discovered this while doing some research for a post the other day: https://vale.rocks/posts/hacker-news https://vale.rocks/posts/hacker-news
- SeanLuke 2mo agoI recall HN originally using Arc. Is there a history available regarding its development and redevelopment?
- maleldil 2mo agoIt still uses Arc. The original implementation was written in Racket, then rewritten in Common Lisp and run on SBCL.
- dmux 2mo agoI know Racket was reworked to build upon Chez Scheme several years ago. If the HN migration to CL was due to performance reasons, I wonder if sticking it out and waiting for the Chez version of Racket would have paid off.
- vindarel 2mo agohere: I’m curious: was Arc running Racket BC or CS? I understand it got a big performance boost after switching to Chez Scheme. dang: It was running BC. I had high hopes for switching to CS because I'd heard the same thing you had, but when I tried it, HN slowed to a crawl. This stuff is so unpredictable. https://news.ycombinator.com/item?id=47140657 https://news.ycombinator.com/item?id=47140657
- soegaard 2mo agoIt was running an old version of BC. I can't remember the details, but I recall that Arc was pinned to an older version of Racket and didn't benefit from improvements to BC and then later to CS. But ... be aware that the Arc interpreter is much more dynamic than Racket, so in general normal Racket programs are more efficient than Arc programs.
- leonmeng 2mo agoSB-MANUAL looks great—having the manual available through docstrings and SLIME should make SBCL development much more pleasant.
- unfirehose 2mo agocheckout lumbda dot com if you are into lisp / scheme