diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2023-11-02 22:17:14 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2023-11-02 22:17:14 +0100 |
| commit | 9b1c9371333e20611ec5422e660ebec7e66c4261 (patch) | |
| tree | 4d0d0dbb27056871ab7c81c2903899e4e639b566 | |
| parent | a61382e9dec22ea1ff3fea2d59d3c605c0aa2aac (diff) | |
| download | nissy-core-9b1c9371333e20611ec5422e660ebec7e66c4261.tar.gz nissy-core-9b1c9371333e20611ec5422e660ebec7e66c4261.zip | |
Added avx2 moves
Diffstat (limited to '')
| -rw-r--r-- | README.md | 12 | ||||
| -rw-r--r-- | src/_moves_avx2.c | 199 | ||||
| -rw-r--r-- | src/cube.c | 49 | ||||
| -rwxr-xr-x | utils/genmovecode.sh | 19 | ||||
| -rwxr-xr-x | utils/gentranscode.sh | 1 |
5 files changed, 266 insertions, 14 deletions
| @@ -15,10 +15,7 @@ $ make test | |||
| 15 | 15 | ||
| 16 | ### Make AVX2 work | 16 | ### Make AVX2 work |
| 17 | 17 | ||
| 18 | * inline moves for avx2 | ||
| 19 | * fix base get_ and set_ macros (constant arguments?) | 18 | * fix base get_ and set_ macros (constant arguments?) |
| 20 | * optimize inverse for avx2 | ||
| 21 | * other things to optimize? | ||
| 22 | 19 | ||
| 23 | ### Documentation and interface | 20 | ### Documentation and interface |
| 24 | 21 | ||
| @@ -37,10 +34,13 @@ $ make test | |||
| 37 | * Takes as parameters the amount of memory to use and a FILE for the tables | 34 | * Takes as parameters the amount of memory to use and a FILE for the tables |
| 38 | * Use multi-move (up to 4/5 moves at once) | 35 | * Use multi-move (up to 4/5 moves at once) |
| 39 | 36 | ||
| 40 | ### Things I need to learn: | 37 | ### Future optimizations |
| 41 | 38 | ||
| 42 | * Inspect compiled assembly | 39 | * CO is the worst part of moving, transforming and inverting. Try basing |
| 43 | * Use valgrind tool cachegrind and other profiling tools | 40 | everything on representing the cube without CO and apply it only at the |
| 41 | end to check that it is actually solved. | ||
| 42 | * see if vcube's method to flip all corners is better | ||
| 43 | * find a better way for computing the inverse? | ||
| 44 | 44 | ||
| 45 | ## Internal representation of the cube | 45 | ## Internal representation of the cube |
| 46 | 46 | ||
diff --git a/src/_moves_avx2.c b/src/_moves_avx2.c index d72f45f..0c1f6a3 100644 --- a/src/_moves_avx2.c +++ b/src/_moves_avx2.c | |||
| @@ -1,2 +1,197 @@ | |||
| 1 | /* TODO: return compose(c, (some avx garbage)); | 1 | static inline cube_t |
| 2 | */ | 2 | inline_move_U(cube_t c) |
| 3 | { | ||
| 4 | cube_t m = _mm256_set_epi8( | ||
| 5 | 0, 0, 0, 0, 11, 10, 9, 8, 7, 6, 0, 1, 3, 2, 5, 4, | ||
| 6 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 1, 0, 3, 2, 4, 5 | ||
| 7 | ); | ||
| 8 | |||
| 9 | return _mm256_shuffle_epi8(c, m); | ||
| 10 | } | ||
| 11 | |||
| 12 | static inline cube_t | ||
| 13 | inline_move_U2(cube_t c) | ||
| 14 | { | ||
| 15 | cube_t m = _mm256_set_epi8( | ||
| 16 | 0, 0, 0, 0, 11, 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, | ||
| 17 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 4, 5, 3, 2, 0, 1 | ||
| 18 | ); | ||
| 19 | |||
| 20 | return _mm256_shuffle_epi8(c, m); | ||
| 21 | } | ||
| 22 | |||
| 23 | static inline cube_t | ||
| 24 | inline_move_U3(cube_t c) | ||
| 25 | { | ||
| 26 | cube_t m = _mm256_set_epi8( | ||
| 27 | 0, 0, 0, 0, 11, 10, 9, 8, 7, 6, 1, 0, 3, 2, 4, 5, | ||
| 28 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 0, 1, 3, 2, 5, 4 | ||
| 29 | ); | ||
| 30 | |||
| 31 | return _mm256_shuffle_epi8(c, m); | ||
| 32 | } | ||
| 33 | |||
| 34 | static inline cube_t | ||
| 35 | inline_move_D(cube_t c) | ||
| 36 | { | ||
| 37 | cube_t m = _mm256_set_epi8( | ||
| 38 | 0, 0, 0, 0, 11, 10, 9, 8, 3, 2, 5, 4, 6, 7, 1, 0, | ||
| 39 | 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 5, 4, 6, 7, 1, 0 | ||
| 40 | ); | ||
| 41 | |||
| 42 | return _mm256_shuffle_epi8(c, m); | ||
| 43 | } | ||
| 44 | |||
| 45 | static inline cube_t | ||
| 46 | inline_move_D2(cube_t c) | ||
| 47 | { | ||
| 48 | cube_t m = _mm256_set_epi8( | ||
| 49 | 0, 0, 0, 0, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0, | ||
| 50 | 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 5, 4, 2, 3, 1, 0 | ||
| 51 | ); | ||
| 52 | |||
| 53 | return _mm256_shuffle_epi8(c, m); | ||
| 54 | } | ||
| 55 | |||
| 56 | static inline cube_t | ||
| 57 | inline_move_D3(cube_t c) | ||
| 58 | { | ||
| 59 | cube_t m = _mm256_set_epi8( | ||
| 60 | 0, 0, 0, 0, 11, 10, 9, 8, 2, 3, 5, 4, 7, 6, 1, 0, | ||
| 61 | 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 4, 7, 6, 1, 0 | ||
| 62 | ); | ||
| 63 | |||
| 64 | return _mm256_shuffle_epi8(c, m); | ||
| 65 | } | ||
| 66 | |||
| 67 | static inline cube_t | ||
| 68 | inline_move_R(cube_t c) | ||
| 69 | { | ||
| 70 | cube_t m = _mm256_set_epi8( | ||
| 71 | 0, 0, 0, 0, 4, 10, 9, 7, 11, 6, 5, 8, 3, 2, 1, 0, | ||
| 72 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 35, 32, 4, 69, 2, 1, 70 | ||
| 73 | ); | ||
| 74 | |||
| 75 | return compose(c, m); | ||
| 76 | } | ||
| 77 | |||
| 78 | static inline cube_t | ||
| 79 | inline_move_R2(cube_t c) | ||
| 80 | { | ||
| 81 | cube_t m = _mm256_set_epi8( | ||
| 82 | 0, 0, 0, 0, 8, 10, 9, 11, 4, 6, 5, 7, 3, 2, 1, 0, | ||
| 83 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 6, 4, 0, 2, 1, 3 | ||
| 84 | ); | ||
| 85 | |||
| 86 | return _mm256_shuffle_epi8(c, m); | ||
| 87 | } | ||
| 88 | |||
| 89 | static inline cube_t | ||
| 90 | inline_move_R3(cube_t c) | ||
| 91 | { | ||
| 92 | cube_t m = _mm256_set_epi8( | ||
| 93 | 0, 0, 0, 0, 7, 10, 9, 4, 8, 6, 5, 11, 3, 2, 1, 0, | ||
| 94 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 32, 35, 4, 70, 2, 1, 69 | ||
| 95 | ); | ||
| 96 | |||
| 97 | return compose(c, m); | ||
| 98 | } | ||
| 99 | |||
| 100 | static inline cube_t | ||
| 101 | inline_move_L(cube_t c) | ||
| 102 | { | ||
| 103 | cube_t m = _mm256_set_epi8( | ||
| 104 | 0, 0, 0, 0, 11, 6, 5, 8, 7, 9, 10, 4, 3, 2, 1, 0, | ||
| 105 | 0, 0, 0, 0, 0, 0, 0, 0, 34, 6, 5, 33, 3, 68, 71, 0 | ||
| 106 | ); | ||
| 107 | |||
| 108 | return compose(c, m); | ||
| 109 | } | ||
| 110 | |||
| 111 | static inline cube_t | ||
| 112 | inline_move_L2(cube_t c) | ||
| 113 | { | ||
| 114 | cube_t m = _mm256_set_epi8( | ||
| 115 | 0, 0, 0, 0, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, | ||
| 116 | 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 5, 7, 3, 1, 2, 0 | ||
| 117 | ); | ||
| 118 | |||
| 119 | return _mm256_shuffle_epi8(c, m); | ||
| 120 | } | ||
| 121 | |||
| 122 | static inline cube_t | ||
| 123 | inline_move_L3(cube_t c) | ||
| 124 | { | ||
| 125 | cube_t m = _mm256_set_epi8( | ||
| 126 | 0, 0, 0, 0, 11, 5, 6, 8, 7, 10, 9, 4, 3, 2, 1, 0, | ||
| 127 | 0, 0, 0, 0, 0, 0, 0, 0, 33, 6, 5, 34, 3, 71, 68, 0 | ||
| 128 | ); | ||
| 129 | |||
| 130 | return compose(c, m); | ||
| 131 | } | ||
| 132 | |||
| 133 | static inline cube_t | ||
| 134 | inline_move_F(cube_t c) | ||
| 135 | { | ||
| 136 | cube_t m = _mm256_set_epi8( | ||
| 137 | 0, 0, 0, 0, 11, 10, 19, 16, 7, 6, 5, 4, 24, 2, 1, 25, | ||
| 138 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 64, 5, 66, 3, 38, 1, 36 | ||
| 139 | ); | ||
| 140 | |||
| 141 | return compose(c, m); | ||
| 142 | } | ||
| 143 | |||
| 144 | static inline cube_t | ||
| 145 | inline_move_F2(cube_t c) | ||
| 146 | { | ||
| 147 | cube_t m = _mm256_set_epi8( | ||
| 148 | 0, 0, 0, 0, 11, 10, 8, 9, 7, 6, 5, 4, 0, 2, 1, 3, | ||
| 149 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, 5, 6, 3, 0, 1, 2 | ||
| 150 | ); | ||
| 151 | |||
| 152 | return _mm256_shuffle_epi8(c, m); | ||
| 153 | } | ||
| 154 | |||
| 155 | static inline cube_t | ||
| 156 | inline_move_F3(cube_t c) | ||
| 157 | { | ||
| 158 | cube_t m = _mm256_set_epi8( | ||
| 159 | 0, 0, 0, 0, 11, 10, 16, 19, 7, 6, 5, 4, 25, 2, 1, 24, | ||
| 160 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 66, 5, 64, 3, 36, 1, 38 | ||
| 161 | ); | ||
| 162 | |||
| 163 | return compose(c, m); | ||
| 164 | } | ||
| 165 | |||
| 166 | static inline cube_t | ||
| 167 | inline_move_B(cube_t c) | ||
| 168 | { | ||
| 169 | cube_t m = _mm256_set_epi8( | ||
| 170 | 0, 0, 0, 0, 18, 17, 9, 8, 7, 6, 5, 4, 3, 26, 27, 0, | ||
| 171 | 0, 0, 0, 0, 0, 0, 0, 0, 65, 6, 67, 4, 39, 2, 37, 0 | ||
| 172 | ); | ||
| 173 | |||
| 174 | return compose(c, m); | ||
| 175 | } | ||
| 176 | |||
| 177 | static inline cube_t | ||
| 178 | inline_move_B2(cube_t c) | ||
| 179 | { | ||
| 180 | cube_t m = _mm256_set_epi8( | ||
| 181 | 0, 0, 0, 0, 10, 11, 9, 8, 7, 6, 5, 4, 3, 1, 2, 0, | ||
| 182 | 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 4, 1, 2, 3, 0 | ||
| 183 | ); | ||
| 184 | |||
| 185 | return _mm256_shuffle_epi8(c, m); | ||
| 186 | } | ||
| 187 | |||
| 188 | static inline cube_t | ||
| 189 | inline_move_B3(cube_t c) | ||
| 190 | { | ||
| 191 | cube_t m = _mm256_set_epi8( | ||
| 192 | 0, 0, 0, 0, 17, 18, 9, 8, 7, 6, 5, 4, 3, 27, 26, 0, | ||
| 193 | 0, 0, 0, 0, 0, 0, 0, 0, 67, 6, 65, 4, 37, 2, 39, 0 | ||
| 194 | ); | ||
| 195 | |||
| 196 | return compose(c, m); | ||
| 197 | } | ||
| @@ -269,6 +269,7 @@ static char *transstr[] = { | |||
| 269 | [BLm] = "mirrored BL", | 269 | [BLm] = "mirrored BL", |
| 270 | }; | 270 | }; |
| 271 | 271 | ||
| 272 | static inline cube_t inline_compose(cube_t, cube_t); | ||
| 272 | static bool isconsistent(cube_t); | 273 | static bool isconsistent(cube_t); |
| 273 | static cube_t flipallcorners(cube_t); | 274 | static cube_t flipallcorners(cube_t); |
| 274 | static uint8_t readco(char *); | 275 | static uint8_t readco(char *); |
| @@ -909,18 +910,49 @@ cube_t | |||
| 909 | inverse(cube_t c) | 910 | inverse(cube_t c) |
| 910 | { | 911 | { |
| 911 | /* TODO: optimize for avx2 */ | 912 | /* TODO: optimize for avx2 */ |
| 912 | uint8_t i, piece, orien; | ||
| 913 | cube_t ret; | 913 | cube_t ret; |
| 914 | 914 | ||
| 915 | setzero(ret); | ||
| 916 | |||
| 917 | #ifdef DEBUG | 915 | #ifdef DEBUG |
| 918 | if (!isconsistent(c)) { | 916 | if (!isconsistent(c)) { |
| 919 | fprintf(stderr, "inverse error, inconsistent cube\n"); | 917 | fprintf(stderr, "inverse error, inconsistent cube\n"); |
| 918 | setzero(ret); | ||
| 920 | return ret; | 919 | return ret; |
| 921 | } | 920 | } |
| 922 | #endif | 921 | #endif |
| 923 | 922 | ||
| 923 | #ifdef CUBE_AVX2 | ||
| 924 | /* Method taken from Andrew Skalski's vcube[1]. The addition sequence | ||
| 925 | * was generated using [2]. | ||
| 926 | * [1] https://github.com/Voltara/vcube | ||
| 927 | * [2] http://wwwhomes.uni-bielefeld.de/achim/addition_chain.html | ||
| 928 | */ | ||
| 929 | cube_t v3, vi; | ||
| 930 | |||
| 931 | v3 = _mm256_shuffle_epi8(c, c); | ||
| 932 | v3 = _mm256_shuffle_epi8(v3, c); | ||
| 933 | vi = _mm256_shuffle_epi8(v3, v3); | ||
| 934 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 935 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 936 | vi = _mm256_shuffle_epi8(vi, v3); | ||
| 937 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 938 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 939 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 940 | vi = _mm256_shuffle_epi8(vi, c); | ||
| 941 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 942 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 943 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 944 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 945 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 946 | vi = _mm256_shuffle_epi8(vi, v3); | ||
| 947 | vi = _mm256_shuffle_epi8(vi, vi); | ||
| 948 | ret = _mm256_shuffle_epi8(vi, c); | ||
| 949 | |||
| 950 | return flipallcorners(ret); | ||
| 951 | #else | ||
| 952 | uint8_t i, piece, orien; | ||
| 953 | |||
| 954 | setzero(ret); | ||
| 955 | |||
| 924 | for (i = 0; i < 12; i++) { | 956 | for (i = 0; i < 12; i++) { |
| 925 | piece = get_edge(c, i); | 957 | piece = get_edge(c, i); |
| 926 | orien = piece & _eobit; | 958 | orien = piece & _eobit; |
| @@ -932,12 +964,13 @@ inverse(cube_t c) | |||
| 932 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; | 964 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; |
| 933 | set_corner(ret, piece & _pbits, i | orien); | 965 | set_corner(ret, piece & _pbits, i | orien); |
| 934 | } | 966 | } |
| 967 | #endif | ||
| 935 | 968 | ||
| 936 | return ret; | 969 | return ret; |
| 937 | } | 970 | } |
| 938 | 971 | ||
| 939 | cube_t | 972 | static inline cube_t |
| 940 | compose(cube_t c1, cube_t c2) | 973 | inline_compose(cube_t c1, cube_t c2) |
| 941 | { | 974 | { |
| 942 | cube_t ret; | 975 | cube_t ret; |
| 943 | 976 | ||
| @@ -992,6 +1025,12 @@ compose(cube_t c1, cube_t c2) | |||
| 992 | } | 1025 | } |
| 993 | 1026 | ||
| 994 | cube_t | 1027 | cube_t |
| 1028 | compose(cube_t c1, cube_t c2) | ||
| 1029 | { | ||
| 1030 | return inline_compose(c1, c2); | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | cube_t | ||
| 995 | transform(cube_t c, trans_t t) | 1034 | transform(cube_t c, trans_t t) |
| 996 | { | 1035 | { |
| 997 | cube_t ret; | 1036 | cube_t ret; |
diff --git a/utils/genmovecode.sh b/utils/genmovecode.sh new file mode 100755 index 0000000..c389ea8 --- /dev/null +++ b/utils/genmovecode.sh | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | type="${1:-src}" | ||
| 4 | |||
| 5 | gcc -DDEBUG h48_to_"$type".c ../src/cube.c -o h48_to_"$type" | ||
| 6 | |||
| 7 | genfuncs() { | ||
| 8 | for f in move_??_*.txt; do | ||
| 9 | move="$(echo $f | sed 's/.*_// ; s/\.txt//')" | ||
| 10 | printf 'static inline cube_t\ninline_move_%s' "$move" | ||
| 11 | printf '(cube_t c)\n{\n' | ||
| 12 | printf '\tcube_t m = ' | ||
| 13 | ./h48_to_"$type" <"$f" | sed '2,4s/^/\t/' | ||
| 14 | printf ';\n\n\treturn compose(c, m);\n}\n\n' | ||
| 15 | done | ||
| 16 | } | ||
| 17 | |||
| 18 | genfuncs | ||
| 19 | rm -f h48_to_"$type" invert | ||
diff --git a/utils/gentranscode.sh b/utils/gentranscode.sh index e874ad4..7749ba7 100755 --- a/utils/gentranscode.sh +++ b/utils/gentranscode.sh | |||
| @@ -23,7 +23,6 @@ genfuncs() { | |||
| 23 | for f in transform_??_???.txt; do | 23 | for f in transform_??_???.txt; do |
| 24 | trans="$(echo $f | sed 's/.*_// ; s/\.txt//')" | 24 | trans="$(echo $f | sed 's/.*_// ; s/\.txt//')" |
| 25 | printf 'static inline cube_t\ninline_trans_%s' "$trans" | 25 | printf 'static inline cube_t\ninline_trans_%s' "$trans" |
| 26 | [ "$1" = "-i" ] && printf '_inverse' | ||
| 27 | printf '(cube_t c)\n{\n' | 26 | printf '(cube_t c)\n{\n' |
| 28 | printf '\tcube_t ret;\n\n' | 27 | printf '\tcube_t ret;\n\n' |
| 29 | printf '\tcube_t tn = ' | 28 | printf '\tcube_t tn = ' |
