3 ms·
The vector extension has many good properties, like the ability to adapt to various size/complexity of processors: it can be implemented slowly on a small proce
by SuchAnonMuchWow 5y ago
The vector extension has many good properties, like the ability to adapt to various size/complexity of processors: it can be implemented slowly on a small processor, and quickly on fast processor. This is because the instructions are very abstract and most of the control is done by the core instead of the compiler, like splitting the vectors into chunks that can be computed per cycle by the core.
But then you loose the fixed instruction execution time: if you configure your registers to be larger than the compute units of the core, the instruction will take multiple cycles.
Citing wikipedia on RISC archs:
"The main distinguishing feature of RISC architecture is that the instruction set is optimized with a large number of registers and a highly regular instruction pipeline, allowing a low number of clock cycles per instruction (CPI)"
- a highly regular instruction pipeline: Nope
- a low number of clock cycles per instruction (CPI): Nope
In the 80'-90', it became apparent that RISC vs CISC was a moot point, and both types of ISA could be equally efficient. However, I think if you want a universal ISA, CISC is better because it is easier to decompose complex instructions into smaller ones on small processor, rather than to detect patterns of simple instructions and optimize them on a large processor.
This is the direction RISC-V took with the vector extension. But I find it a stretch to call it a RISC ISA then.
- brucehoult 5y agoThanks for the reply. >But then you loose the fixed instruction execution time: if you configure your registers to be larger than the compute units of the core, the instruction will take multiple cycles. "multiple" doesn't imply "not fixed". Floating Point on pretty much any modern CPU, CISC or RISC, takes 3 or 4 clock cycles for add/subtract/multiply/FMA. It's not 1 cycle, but it's always the same. This means the compiler can (if it's told what CPU the code will be running on with -mtune or whatever) accurately schedule the code for maximum efficiency. And usually the FPU will be pipelined, so you can start a new add or multiply every clock cycle, as long as it doesn't depend on the result of a very recent one. Recently I've been using the Allwinner D1, which implements draft version 0.7.1 of the RISC-V Vector ISA with 128 bit registers. Like an FPU, most instructions take 3 clock cycles with LMUL=1. If you increase LMUL then, yes, the instructions take longer, but it is deterministic and you can do your instruction scheduling around it. If you look at the result of a vectorised memcpy() I did on the D1, you can see that the execution time is absolutely identical at 30.9 ns (31 clock cycles at 1.008 GHz) from sz=0 to sz=64 http://hoult.org/d1_memcpy.txt http://hoult.org/d1_memcpy.txt At sz=0 this is 60% of the time for the standard scalar memcpy() in glibc!! By sz=64 it is 3.6 times faster than the standard memcpy(). I'm using LMUL=4 there. LMUL=2 provided slightly lower latency for sz<=32 but couldn't achieve as much speed in cache. LMUL=8 didn't provide any more speed in cache but had latency closer to the standard scalar code (but still less than it) for sz=0.
- SuchAnonMuchWow 5y agoI never actually wrote programs with risc-v vectors instructions, only for other ISA, so you seems to have much more experience than me on on that. Thanks for sharing your experience, and for the discussion. > "multiple" doesn't imply "not fixed". But in the case of risc-v, it really is "not fixed". For example, can you tell me the number of cycle it takes to execute this instruction: `vadd.vv v3, v1, v2` ? Another example, in your implementation of memcpy: ``` 0: 86aa mv a3,a0 0000000000000002 <.L1^B1>: 2: 00267757 vsetvli a4,a2,e8,m4,d1 6: 12058007 vlb.v v0,(a1) a: 95ba add a1,a1,a4 c: 8e19 sub a2,a2,a4 e: 02068027 vsb.v v0,(a3) 12: 96ba add a3,a3,a4 14: f67d bnez a2,2 <.L1^B1> 16: 8082 ret ``` From what I understand, you can't tell how long each vlb.v or vsb.v will take on a given processor, as it depend on the number of elements that will be returned in a4. The last iteration of the loop for example will probably take less time than the others, because the instructions will only have to load and store the trailing part of the data. > If you look at the result of a vectorised memcpy() I did on the D1, you can see that the execution time is absolutely identical at 30.9 ns (31 clock cycles at 1.008 GHz) from sz=0 to sz=64 Again, I'm not arguing against the efficiency of RISC-V vector extension. I'm sure any processor designer will be able to implement it as efficiently as if the instructions were closer to the raw compute logic. I'm not even arguing against the extension. If anything, I think I would prefer if an open CISC ISA was gaining popularity as an open source platform instead of RISC-V, because it would have the same portability implications, but with smaller code size and memory footprint, and while leaving a lot of room for innovation and optimization on the actual design. What I actually argue against is calling it a RISC ISA, because while the core of the ISA is RISC, this vector extension is not.
- brucehoult 5y agoActually I can. I can tell you that on the chip I'm currently using "vadd.vv v3, v1, v2" takes 3 clock cycles for LMUL=1, 6 clock cycles for LMUL=2, 12 clock cycles for LMUL=4, and 24 clock cycles for LMUL=8. You always have to know what current LMUL you have, otherwise you can try to use illegal register numbers. For example in LMUL=8 you can only use v0, v8, v16, and v24. Anything else causes an exception. "From what I understand, you can't tell how long each vlb.v or vsb.v will take on a given processor, as it depend on the number of elements that will be returned in a4. The last iteration of the loop for example will probably take less time than the others, because the instructions will only have to load and store the trailing part of the data." If you look at the link I provided, you will see that's not the case. The memcpy() function takes absolutely identical time for any memcpy() length from 0 bytes to 64 bytes. It does not depend on the number of active elements. At least on this chip, which is currently the only chip in the world you can get your hands on with a RISC-V Vector unit. On some other chip it might take a different amount of time. But on this one, and probably many others, it takes the same amount of time. "I think I would prefer if an open CISC ISA [...] with smaller code size and memory footprint" CISC ISAs do not have smaller code size. The two most compact code modern full-featured ISAs are ARMv7 and RISC-V. They are smaller than i686 by quite a margin. In 64 bit there is absolutely no competition. RISC-V is the smallest code, with ARMv8 and AMD64 quite similar to each other but significantly bigger. Just look at the same programs compiled for each one and you'll see. I suggest something like Ubuntu 21.04, which is available for all three. Take a look in /bin and /usr/bin and run "size" on the binaries. It's indisputable. RISC-V is the clear winner in 64 bit ISAs. ARMHF is similar or a little bit more compact in 32 bit. CISC x86 isn't close in either case.