HN user

feffe

110 karma
Posts0
Comments70
View on HN
No posts found.

I've never been able to fix the tool calling issues. Running unsloth versions with llama.cpp, constant issues. Have tried many forum fixes, including lots of fixed chat templates, to no avail. It's mostly the edit call that breaks, which often results in "let me just rewrite the whole file from context".

All ALU operations are also more expensive with 32 bit operands. So 16 bit data bus, 24 bit address bus. Slower arithmetic with 32 bit operands. I never though of it as a 32 bit CPU.

I'm a believer in restricting the scope of definitions as much as possible, and like programming languages that allows creating local bindings for creating another.

For example:

    local
        val backupIntervalHours = 24
        val approxBackupDurationHours = 2
        val wiggleRoomHours = 2
    in
    val ageAlertThresholdHours = backupIntervalHours + approxBackupDurationHours + wiggleRoomHours
    end
Then it's easier to document what components a constant is composed of using code without introducing unnecessary bindings in the scope of the relevant variable. Sure constants are just data, but the first questions that pops into my head when seeing something in unfamiliar code is "What is the purpose of this?", and the smaller the scope, the faster it can be discarded.

Steam on Linux works really well now. I sort of built my own steam machine a few months back with a framework desktop that now sits in my TV rack. Gaming on it is a really good experience. Had to buy a PS5 controller though because I could not get the XBOX controller to work over bluetooth which was a bit of a bummer. For me the new controller is most interesting as most games have XBOX controller support (with xbox button captions) and the steam controller adopts the button naming.

In Defense of C++ 10 months ago

CMake has become the defacto standard in many ways, but I don't think it's that easy to deal with. There's often some custom support code in a project (just as with make files) that you need to learn the intricacies of, and also external 3pp modules that solve particular integration issues with building software that you also need to learn.

For me, base CMake is pretty easy by now, but I'd rather troubleshoot a makefile than some obscure 3pp CMake module that doesn't do what I want. Plain old makefiles are very hackable for better or worse [1]. It's easy to solve problems with make (in bespoke ways), and at the same time this is the big issue, causing lots of custom solutions of varying correctness.

[1]: Make is easy the same way C is easy.

I don't see the point of passing the size to a "free" function. I don't see how it could be used to speed up de-allocation. Additionally most usage would probably not want to keep the size around.

But I concur that realloc is mostly pointless. For code that want to grow or shrink, I think it's much better for it to know the data block size. I think there's very little opportunity to happen to have free memory next to your allocation that can be "grown into". At least for slab like allocators, so the growing room is minimal.

It's a bit difficult to unify all APIs because data will be needlessly passed around, when in most cases you don't care. Aligned allocation may also need a slightly different implementation anyway.

realloc and calloc are warts in my book...

Hmm, I was a hang around back in the day. Not one of the big boys. But I got to say some of the young kids that I hung around with then had more skills than many I've worked with in the industry since. Going on my 25th year as a "professional" SW developer.

Perhaps this is similar to how they work in go?

"var x []int; fmt.Printf(`%p %d`, x, len(x))" outputs "0x0 0"

Indexing "x[0]" results in: "panic: runtime error: index out of range [0] with length 0"

They can also be appended to and then produce a valid slice.

I think most applications don't have any dependency towards a specific page size. They use malloc (C) or new (C++) to allocate memory which does not expose this constraint.

You need to care if using mmap directly to map files or other resources into the virtual memory address space. The default page size can be queried using for example sysconf() on Linux. I guess something like garbage collectors in language run-times would also use mmap directly as it's most likely to side step malloc/new.

An application would normally not use madvise, unless also using mmap for some special purpose.

It depends on the CPU architecture how flexible it is with different page sizes. For example, from what I recall, MIPS was extremely flexible and allowed any even power of two size for any TLB entry.

x86_64 only support three different page sizes, 4 kB, 2 MB and 1 GB and there are limitations wrt the number of TLB entries that can be used for the larger page sizes.

So, yea, there are bound to be regressions if just trying to switch to 2 MB as a default but I think it should be doable. Not all archs use 4 kB to begin with.

Can the CPU cores in a CCD access the L3 cache of another CCD with higher latency? If so the CCD without extra cache may still get a performance boost.

I know there has been such designs in the past but I don't know how it works in the Ryzen CPUs.

There are many contradicting examples:

The original JPEG standard is an ISO standard (ISO/IEC 10918) with payed access.

MP3 is also an ISO standard (ISO/IEC 13818-3). Perhaps not as relevant today but was once used by basically everyone.

Access to the standard is only relevant to the implementer. It's of no consequence to users of a piece of software.

Nitpicking on terminology. Portable used to mean that software can run on another platform with minimal modifications. Typically by relying on abstraction layers that then has multiple implementations. It's cool that a single executable can run on both Windows and some Unixes but that's something else than what portable used to mean.

portable = able to port

I think a mindset that could work is to accept software as done. This is hard but for foundational stuff it could work well. Only fix bugs in such software. Try to set a scope what the software should do, build it, then do maintenance on it. Supersede it entirely to add new functionality.

That's my armchair take on it.

ASAN is pretty great with these cases as well. Spent much time looking for the needle in the haystack before ASAN came along.

In my experience debuggers handles this fine. Some archs also has a link register (jump and link) which may help finding back. This test is from x86-64 Linux.

  /*
  gcc -g -Wall -o x x.c
  gdb ./x
  (gdb) r
  (gdb) bt
  #0  0x0000000000000000 in ?? ()
  #1  0x0000555555554617 in foo () at x.c:6
  #2  0x0000555555554628 in main () at x.c:10
  (gdb) f 1
  #1  0x0000555555554617 in foo () at x.c:6
  6           bar();
  (gdb) p bar
  $1 = (void (*)(void)) 0x0
  */
  
  #include <stddef.h>
  
  void (*bar)(void) = NULL;
  
  void foo() {
      bar();
  }
  
  int main() {
      foo();
  }

Yes, you are correct. I had not thought about it deeply. There are restrictions for what can be used as a map keys according to some built-in equality rules. And of course the types used as map keys and values are concrete types so you can't pass a map to generic functions pre generics.

But was the built-in append function generic pre generics? I think it is?

Built-in map and vector types are generic.

E.g. map[int]*MyType

Using interface{} is quite common in the absence of sum types (or inheritance with base class). I guess interface{} is like Object in Java.

It's not worse than Python or other dynamic languages that many people are fine with. The run-time panics when asserting that a type is something it's not.

E.g. https://go.dev/play/p/c4hx8HSiB8I

That said, no, it's not optimal and could be better (IMHO).

Go 1.18 4 years ago

The compiler is fast in that is compiles code quickly, just as Go and the execution speed of produced programs are similar to Go (depending on what abstractions you use).

It seems there are a bunch of languages in the fast but not quite as fast as C/C++ category: Java, C#, Go, OCaml, SBCL (Lisp), Haskell

Not weird but I can share what has worked for me so far.

I'm pretty skinny but like to eat junk food and candy. My target weight is 80-82 kg. When I hit 90 kg I don't feel good about myself. Pants too tight etc.

First time I hit 90 kg was 2013. I tried intermittent fasting 8/16. This worked really well for me at that time. I lost weight really quickly. I could even continue my bad eating habits within the 8 hour window where eating is allowed and still loose weight.

I've stuck with a 8/16 diet with cheating up till now. Beginning of this year I hit 90 kg again. My old intermittent fasting diet did not seem to have the same effect any more (granted I cheated quite a bit at the end). I tried mixing it with Keto, counting every kcal, grams of carbs and fat in a log book. In one month I lost 8 kg so I think it was successful. I'm off Keto for now but I may be a trick you want to try. My main takeaways from Keto is that it really does take away your cravings. I could also do longer periods of fasting (did 36 hours two times) which I think would have been very hard for me when on a carb rich diet.

Well yes, I was one of the haters back then because it was too verbose (for me). IMHO Go is less verbose than early Java.

It could be less verbose without loosing readability. My two top picks would be to add a ternary expression and a real while loop so that you could write better iterators.

while next := some.Next(); next != nil { // ... }

Such a while loop would be consistent with the if statement support for an assignment and following check.

Go Annoyances 4 years ago

Everyone will have different gripes based on previous experience.

I once religiously wrote Doxygen (aka javadoc) comments for all my C code. Eventually I realized it was just very verbose red tape that added little value. In C no-one bothers to actually generate or read the generated Doxygen HTML output. It's just waste. Granted in Java this is not the case as javadoc is more permeated into the culture. Anywho, personally I'm glad the Go designers went with something more lightweight that focuses on the essentials. All just personal preferences...

WRT logging, can it be done right? I think in most circumstances the right answer is to not log anything at all. Logging poisons the code you are writing, forcing the user of your code to relate to the same logging APIs as you choose. Maybe they will have 10s, 100s of different logging APIs to relate to in the final program. If you are writing reusable code for others I think the answer is to avoid logging to the largest extent possible. Otherwise do something really simple that the user of your code can control if they want or not.

I've written a lot of C code and to me Go is like a high level C with some sharp corners removed and a GC. Maybe I don't see the limitations in Go as a problem because of this. Have done quite a bit of C++ as well. I prefer simpler languages that I can keep in my head and like C and Go for that reason.

Do I prefer it to rust? I've not bothered to learn rust yet. I think I would like it better than C++ but it's a bit large for my taste. I like to see the language level as an abstraction level that I want to be able to keep entirely in my head. I fear that rust (just as C++) may have too many features for that.