While adapting the H264 standard encoder x264 for RISC-V, we've identified several operations that are challenging to implement efficiently with existing RVV instructions. In some cases, implementations require too many instructions, potentially impacting encoder performance.
...
This is an open collaboration. All ideas and contributions are valuable as we work together to enhance RISC-V's video codec capabilities.
Contact Information
Vector transpose instructions
...
Using RISC-V RVV, we have discovered two methods to perform matrix transposition(thanks camel-cdr for the assistance provided):
- Using segmented load or store
- Using vrgather
Here, we use the example of transposing a 4x8 (2x4x4) matrix (transposing the left 4x4 and the right 4x4 separately) to illustrate these two methods.
Segmented load or store
In this way, we can use the `vssseg4e16.v` instruction to store each row of the original matrix into memory by columns, and then read them back by rows. Since we are transposing a 4x8 matrix, we also need to use `vslide` to combine the contents of the two registers together.
Code Block |
---|
// Using extra loads and stores, and use vslide to combine them .macro TRANSPOSE4x8_16 buf, bstride, v0, v1, v2, v3, t0, t1, t2, t3 vssseg4e16.v \v0, (\buf), \bstride vsetivli zero, 4, e16, mf2, ta, ma vle16.v \v0, (\buf) add \buf, \buf, \bstride vle16.v \v1, (\buf) add \buf, \buf, \bstride vle16.v \v2, (\buf) add \buf, \buf, \bstride vle16.v \v3, (\buf) add \buf, \buf, \bstride vle16.v \t0, (\buf) add \buf, \buf, \bstride vle16.v \t1, (\buf) add \buf, \buf, \bstride vle16.v \t2, (\buf) add \buf, \buf, \bstride vle16.v \t3, (\buf) add \buf, \buf, \bstride vsetivli zero, 2, e64, m1, tu, ma vslideup.vi \v0, \t0, 1 vslideup.vi \v1, \t1, 1 vslideup.vi \v2, \t2, 1 vslideup.vi \v3, \t3, 1 .endm function transpose4x8_16_one vsetivli zero, 8, e16, m1, ta, ma mv t0, a0 vl4re16.v v0, (a0) li t1, 8 TRANSPOSE4x8_16 t0, t1, v0, v1, v2, v3, v8, v9, v10, v11 vs4r.v v0, (a0) ret endfunc |
...
For creating index by hand, the idea is to set the index for gathering vector N
to (i&3)*vl+(i&~3u)+N
, where i
is the element index obtained by vid.v.
Code Block |
---|
// Using vrgather with index created by hand .macro TRANSPOSE4x8_16_vrgather v0, v1, v2, v3, t0, t1, t2, t3, t4, t5, t6, t7, s0 vsetivli zero, 8, e16, m1, ta, ma vid.v \t0 li \s0, 8 vand.vi \t1, \t0, 3 vmul.vx \t1, \t1, \s0 vand.vi \t0, \t0, -4 vadd.vv \t4, \t1, \t0 vadd.vi \t5, \t4, 1 vadd.vi \t6, \t4, 2 vadd.vi \t7, \t4, 3 li \s0, 32 vsetvli zero, \s0, e16, m4, ta, ma vrgatherei16.vv \t0, \v0, \t4 vmv.v.v \v0, \t0 .endm function transpose4x8_16_two vl4re16.v v0, (a0) TRANSPOSE4x8_16_vrgather v0, v1, v2, v3, v8, v9, v10, v11, v12, v13, v14, v15, t0 vs4r.v v0, (a0) ret endfunc |
...