#EvalynOS
1 messages · Page 34 of 1
Sorry my wording is ass I haven't slept all day
Trying to reset sleep schedule to not be total BS
The parts of the loop where it checks alignment and other things was causing the 16b part to be slower in alot of cases when not using single byte copies
Though some other changes I made lessened that do maybe I can just swap if back to 8b?
Probably needs more micro benchmarking I don't want to fucking do
And when I compile with -o3 / lto eveything just shits the floor and ends up fast as fuck anyways (but not in an invalid way)
So some of my test methods may not be fully good since it's adhoc shoved into the kernel
I do wonder why when it should be looping and be mostly 1:1 the gap increases instead of not on there
But on x86 it's fine it seems
Both ran on bare metal so no scheduling bs with VMs/tcg
Omg you're still on memset ðŸ˜
@hazy saddle For memcpy, wouldn't it be faster to use ERMS? If you're not targetting a CPU older then 2012
Atleast, that's what i do for my memcpy, I'm not sure if it's faster or slower
__asm__ volatile("rep movsb" : "+D"(Dest), "+S"(Src), "+c"(Count) : : "memory");
I do use that if you would have read the code
Just for copies larger than 2k
Wouldn't it be better to use it for all?
Depends on alignments
Look at the benchmarks for things above 2k
And look how much it can vary
On my 5700x

Above 2kb most of my workloads are going to be page copies of half pages of so
So it's on average best to use it there iirc
ERMS also has startup overhead too
Why not use non temporal loads/stores for this?
Aren't thoes only on SSE registers etc?
Not limited to
What's the instruction for doing then on GPRs?
Also I don't really wanna make it super importable and have a bunch of ifdefs
And I wonder if that's even appropriate for a memcpy
I’d use SSE non temporal instructions for this , there should be gcc intrinsics for this, but I forgot
If you’re copying large amounts of data at a time, these are applicable, as you don’t pollute caches
are non-temporal stores safe to do if the target is in cache?
Yes
It’ll still adhere to the CC policy
I'd probably want an mfence too before returning right? And I presume only normal loads too
Intel are scared of cache incoherence for security reasons
the sdm says
The non-temporal hint is implemented by using a write combining (WC) memory type protocol when writing the data to memory. Using this protocol, the processor does not write the data into the cache hierarchy, nor does it fetch the corresponding cache line from memory into the cache hierarchy.
loads from wc mem might be incoherent with stores still in the wc buffer
iirc
I see, if there aren’t loads coming soon after this it should be fine though nah?
I mean memcpy can't overlap and if I do a mfence at the end it should work fine?
Like you can use a fence directly after
i mean, if i understand right, this would be broken? ```
; assume [rdi] != 0
mov eax, [rdi]
xor eax, eax
movnti [rdi], eax
mov eax, [rdi]
; eax might be != 0 because the cache line remains
But if it’s in a wc buffer (assuming this is one of the linefill buffers), it should be forwarded from there first right?
Can this encode a displacement?
That could be an issue with the bulk copies?
It should at least Invalidate the address in cache
at a glance it seems to use modrm so like any other insn?
Nontemporal stores
Godbolt is dumb on mobile and the keyboard never shows up ðŸ˜
I can't test it 
hmm maybe i'm misunderstanding the guarantees
or i'm confusing something
i tried testing it locally with ```x86asm
global main
main:
mov eax, 0x41414141
lea rdi, [rel foo]
mov [rdi], eax
xor eax, eax
movnti [rdi], eax
mov eax, [rdi]
ret
section .data
foo: dd 0x42424242
i think i might be confusing this with wc cacheability on pages from pat
since there reads are treated as uc and bypass any on-cpu buffers
I think that if large data copying is excessive, it may be worth it to try non temporal stores at least (loads you might still not want to use non temporal operations for to allow for the cache to prefetch data you’re copying)
If it improves performance stick with it if not just stick with what you’re using now
But it is probably worthwhile to look into
I think il stick with my current function
And come back and try and fix it up more
But it's probably fineee
And in most cases other than super tiny ops it's alot better
Though this part of my benchmarks were strange
Il try and maybe make a more reliable bench?
could even go further and insert prefetch hint instructions before loads :^)
I feel like in this scenario this would only hurt performance , as the loads would be trivially caught by a simple stride prefetcher
PREFETCHNTA could help maybe?
True that
LTO just fixes thisâ„¢
ðŸ˜
and neither i or clanker can figure out why tf its doing that
horrific
I mean it's probably fine since release builds will want to be done with LTO anyways :p
And it's something I fully support
i wonder if its due to the vf2 being an in order cpu / less fancy?
i wonder if on @tawny wren's clankered riscv core thats more fancy would fare better 
since this also doesnt show in x86
and this ends up being something that the smaller CPU struggles with predicting branches etc and crap
Okay now for me to try and get the energy to review this shit
And commit and push
And then fuck
What was on my list of things to do next?
porting bash
I think there was one other thing than timers?
Right it was the RBtree rework
To save 8 bytes
I'm also thinking about stuff like LAM
Yes it's a cool feature
but
It sucks ass how I can't really use it
On 5 level paging it wouldn't give me enough bits for what id want to use it for
Eg I don't think it can even fit a u8?
And it's really architecture dependant
And even CPU dependant with paging modes
What sucks is I can't run different parts of the address space with different paging modes
Because the kernel could get forced to a 4 level mode
if you are really into saving bits, you can force pointers to be aligned and have your data in the lower bits of the pointers
But even then support is not there yet for it to be viable
Yeah this is what I was gonna do the the BStree
Since they are all 8 byte aligned
And rbtrees only need one bit
and if you are always working with kernel data structures
you can ignore the fact that you dont have lam
you can always or the uppers bits with 0xff...
although this will get very shitty if you have multiple arches
The point of lam is a speed one not an embedding
first thing I get when I search for intel lam lol
Just sucks it's a little not feesible to use even in userspace
> the Linux kernel is now disabling LAM out of security concerns.
Based
LASS was added to address this btw
lmfao
LAM is just stupid on x86
As long as the page walkers aren't flexible
Since a program can't say it wants 4/5 level paging
Atleast then the software could be somewhat portableish
> When LASS is enabled, the processor hardware monitors memory access based on the current CPU privilege level (CPL):
> User Space Access: If user-mode software attempts to access an address in the upper half (kernel space), a General Protection Fault (#GP) is generated.
INTEL
WHY
General fuck you fault
i suppose for guarding against meltdown
welp add another random fucking reason for general protection faults to happen
no, the feature it self is fine
the problem is raising a gp
gps can be caused by like 40 different things atp
the only problem is that you wont be able to send a page fault to the process
but whatever
oh it also prevents the kernel from accessing user memory
This wouldn't be an issue if FRED added GPF source reporting
And they do have fields to allow this btw
for anything segmentation related
it's a uint64_t lol
So the IDT the GDT and the LDT
yes
They have an entire 8 bytes of reserved space btw
259
- 1 per idt entry
- 1 for gdt errors
- 1 for ldt errors
- 1 for "generic error"
not really
if you wanna count 1 per segment selector as well 
I meant I went too far
no you didn't lol
GPF due to SMP startup 
the worst one imo
> Executing an SSE/SSE2/SSE3 instruction that attempts to access a 128-bit memory location that is not aligned on a 16-byte boundary when the instruction requires 16-byte alignment. This condition also applies to the stack segment.
because there is LITERALLY AN EXCEPTION CALLED "ALIGNMENT CHECK"
Well it technically should perform better than the cores in the vf2 per MHz lol
How fast are the cores in the vf2 again?
Like one ghz and in order 2 wide pipeline or some shit
And I mostly mean some weird asf behavior with the memset at O2
And 4 cores iirc?
Where small copies progressively take wayyyy longer than a naive loop despite being the same code
I don't think I'll be able to get my FPGA to beat that raw performance lol
Unless you use lto
It's mostly relative mcycle count between two algorithms I need to see
Doesn't sound that insane but do try to set a mtune argument if you haven't already
wait what??
Not easy performance
My board dosnt have one
Yeah
That's why I tried micro benchmarking so much
It's some sifive core
objdump it and diff?
I even put a clanker on it
And that wouldn't work with LTO memes and other crap
Look at the benchmarks I posted up thetr
I'm more curious in the actual assembly difference if it's the same code
no not same code
i meant the inner loop
that should be executing
between the two functions being benched
for small things
yeah I have no clue, I'm eepy and this isn't making any sense
jesus fuck the diff is insane
lmao
i think it optimized it into the korona memcpy
Or I mean
A similar algorithm ðŸ˜
Just for memset instead
looks like a diff id expect tbh
given what i very quickly googled about the sifive core
ah lol
since its in-order multi-issue the compiler will be trying to schedule the instructions in such a way that the cpu retires as many as possible
since the cpu wont reorder them on its own
Which is also what the korona memcpy does I think? It's basically a bunch of chunks of progressively smaller copies until it does one byte and can return
itll also probably implicitly know a bit more about the core and memory and shit as well, but i wouldnt be surprised if there are other ways to make the generic one do that too since it would make sense in general i think
well time to run a benchmark
lol that fixed it
it still has some losses with strange non word sized alignments above 8b
but thats fine
since its some weird af shit to have a struct thats not word size aligned AND larger than a word size
so it ended up just being a poopy cpu that needed an mtune flag

😔
It's also why this didn't happen on a 5700x
ill be back to chip in in a few months
Because zen3 is a good uarch
Can you no longer afford the word shit?
I fucking wonder
Wdym
The cpu equivalent of hydrogen bomb vs coughing baby
-# would it work on an 8086 
ðŸ˜
i mean
this still has some tricks
its still multi issue
and its not fully weak
a coughing baby would be a super simple core that takes many cycles to execute one opcode and has no fancy tricks
2 pipelines no ooo riscv64 cpu vs god knows how many pipelines, ooo & speculative x86_64 cpu
this is more like a toddler of CPUs
doom guy
i was looking back at my riscv/la64 interrupt code
some of the comments were a little unclear imo?
i changed it from
bnez t1, 1f # branch if from kernel mode
ld t1, 0(t0) # load current thread pointer if from user mode
ld sp, 0(t1) # get kernel stack pointer
1: # else proceed
to
bnez t1, 1f # if from usermode {
ld t1, 0(t0) # load current thread pointer
ld sp, 0(t1) # get kernel stack pointer
1: # }
commit message for tomorrow
Optimize memcpy and memset
Also make risc-v and loongarch64 interrupt comments more clear
actually
i dont know if i should change them?
you care way more about commit messages than me lmao, I just do [<area of the project changed>] make <thing> better most of the time lol
Since I offten have larger commits I try and keep a list of bullet points of crap happening
And I try and keep the main message under 50 characters etc
yea that makes sense