WojciechMula / ternary-logic

Support for ternary logic in SSE, XOP, AVX2 and x86 programs
Other
30 stars 9 forks source link

Reuse of equivalent operations. #2

Closed HJLebbink closed 6 years ago

HJLebbink commented 6 years ago

Is there a particular reason for not reusing parameter permutation equivalent operations. I realized that my compiler only very occasionally reduces equivalent operations. The current 256 operations can be reduced to 80. For example:

template<> __m128i ternary<0x04>(const __m128i C, const __m128i B, const __m128i A) {
    return ternary<0x02>(A, C, B)
}

I'll give a look at the python code to see if I can use the following equivalences:

TERN[4](abc) = TERN[2](acb)
TERN[5](abc) = TERN[3](acb)
TERN[12](abc) = TERN[10](acb)
TERN[13](abc) = TERN[11](acb)
TERN[16](abc) = TERN[2](cba)
TERN[17](abc) = TERN[3](cba)
TERN[18](abc) = TERN[6](bac)
TERN[19](abc) = TERN[7](bac)
TERN[20](abc) = TERN[6](cba)
TERN[21](abc) = TERN[7](cba)
TERN[28](abc) = TERN[26](acb)
TERN[29](abc) = TERN[27](acb)
TERN[32](abc) = TERN[8](bac)
TERN[33](abc) = TERN[9](bac)
TERN[34](abc) = TERN[10](bac)
TERN[35](abc) = TERN[11](bac)
TERN[36](abc) = TERN[24](bac)
TERN[37](abc) = TERN[25](bac)
TERN[38](abc) = TERN[26](bac)
TERN[39](abc) = TERN[27](bac)
TERN[48](abc) = TERN[10](bca)
TERN[49](abc) = TERN[11](bca)
TERN[50](abc) = TERN[14](bac)
TERN[51](abc) = TERN[15](bac)
TERN[52](abc) = TERN[26](bca)
TERN[53](abc) = TERN[27](bca)
TERN[54](abc) = TERN[30](bac)
TERN[55](abc) = TERN[31](bac)
TERN[56](abc) = TERN[44](bac)
TERN[57](abc) = TERN[45](bac)
TERN[58](abc) = TERN[46](bac)
TERN[59](abc) = TERN[47](bac)
TERN[64](abc) = TERN[8](cba)
TERN[65](abc) = TERN[9](cba)
TERN[66](abc) = TERN[24](cba)
TERN[67](abc) = TERN[25](cba)
TERN[68](abc) = TERN[10](cab)
TERN[69](abc) = TERN[11](cab)
TERN[70](abc) = TERN[26](cab)
TERN[71](abc) = TERN[27](cab)
TERN[72](abc) = TERN[40](acb)
TERN[73](abc) = TERN[41](acb)
TERN[74](abc) = TERN[44](acb)
TERN[75](abc) = TERN[45](acb)
TERN[76](abc) = TERN[42](acb)
TERN[77](abc) = TERN[43](acb)
TERN[78](abc) = TERN[46](acb)
TERN[79](abc) = TERN[47](acb)
TERN[80](abc) = TERN[10](cba)
TERN[81](abc) = TERN[11](cba)
TERN[82](abc) = TERN[26](cba)
TERN[83](abc) = TERN[27](cba)
TERN[84](abc) = TERN[14](cba)
TERN[85](abc) = TERN[15](cba)
TERN[86](abc) = TERN[30](cba)
TERN[87](abc) = TERN[31](cba)
TERN[88](abc) = TERN[44](cab)
TERN[89](abc) = TERN[45](cab)
TERN[90](abc) = TERN[60](acb)
TERN[91](abc) = TERN[61](acb)
TERN[92](abc) = TERN[46](cab)
TERN[93](abc) = TERN[47](cab)
TERN[94](abc) = TERN[62](acb)
TERN[95](abc) = TERN[63](acb)
TERN[96](abc) = TERN[40](cba)
TERN[97](abc) = TERN[41](cba)
TERN[98](abc) = TERN[44](bca)
TERN[99](abc) = TERN[45](bca)
TERN[100](abc) = TERN[44](cba)
TERN[101](abc) = TERN[45](cba)
TERN[102](abc) = TERN[60](cba)
TERN[103](abc) = TERN[61](cba)
TERN[108](abc) = TERN[106](acb)
TERN[109](abc) = TERN[107](acb)
TERN[112](abc) = TERN[42](cba)
TERN[113](abc) = TERN[43](cba)
TERN[114](abc) = TERN[46](bca)
TERN[115](abc) = TERN[47](bca)
TERN[116](abc) = TERN[46](cba)
TERN[117](abc) = TERN[47](cba)
TERN[118](abc) = TERN[62](cba)
TERN[119](abc) = TERN[63](cba)
TERN[120](abc) = TERN[106](cba)
TERN[121](abc) = TERN[107](cba)
TERN[122](abc) = TERN[110](bac)
TERN[123](abc) = TERN[111](bac)
TERN[124](abc) = TERN[110](cba)
TERN[125](abc) = TERN[111](cba)
TERN[132](abc) = TERN[130](acb)
TERN[133](abc) = TERN[131](acb)
TERN[140](abc) = TERN[138](acb)
TERN[141](abc) = TERN[139](acb)
TERN[144](abc) = TERN[130](cba)
TERN[145](abc) = TERN[131](cba)
TERN[146](abc) = TERN[134](bac)
TERN[147](abc) = TERN[135](bac)
TERN[148](abc) = TERN[134](cba)
TERN[149](abc) = TERN[135](cba)
TERN[156](abc) = TERN[154](acb)
TERN[157](abc) = TERN[155](acb)
TERN[160](abc) = TERN[136](bac)
TERN[161](abc) = TERN[137](bac)
TERN[162](abc) = TERN[138](bac)
TERN[163](abc) = TERN[139](bac)
TERN[164](abc) = TERN[152](bac)
TERN[165](abc) = TERN[153](bac)
TERN[166](abc) = TERN[154](bac)
TERN[167](abc) = TERN[155](bac)
TERN[176](abc) = TERN[138](bca)
TERN[177](abc) = TERN[139](bca)
TERN[178](abc) = TERN[142](bac)
TERN[179](abc) = TERN[143](bac)
TERN[180](abc) = TERN[154](bca)
TERN[181](abc) = TERN[155](bca)
TERN[182](abc) = TERN[158](bac)
TERN[183](abc) = TERN[159](bac)
TERN[184](abc) = TERN[172](bac)
TERN[185](abc) = TERN[173](bac)
TERN[186](abc) = TERN[174](bac)
TERN[187](abc) = TERN[175](bac)
TERN[192](abc) = TERN[136](cba)
TERN[193](abc) = TERN[137](cba)
TERN[194](abc) = TERN[152](cba)
TERN[195](abc) = TERN[153](cba)
TERN[196](abc) = TERN[138](cab)
TERN[197](abc) = TERN[139](cab)
TERN[198](abc) = TERN[154](cab)
TERN[199](abc) = TERN[155](cab)
TERN[200](abc) = TERN[168](acb)
TERN[201](abc) = TERN[169](acb)
TERN[202](abc) = TERN[172](acb)
TERN[203](abc) = TERN[173](acb)
TERN[204](abc) = TERN[170](acb)
TERN[205](abc) = TERN[171](acb)
TERN[206](abc) = TERN[174](acb)
TERN[207](abc) = TERN[175](acb)
TERN[208](abc) = TERN[138](cba)
TERN[209](abc) = TERN[139](cba)
TERN[210](abc) = TERN[154](cba)
TERN[211](abc) = TERN[155](cba)
TERN[212](abc) = TERN[142](cba)
TERN[213](abc) = TERN[143](cba)
TERN[214](abc) = TERN[158](cba)
TERN[215](abc) = TERN[159](cba)
TERN[216](abc) = TERN[172](cab)
TERN[217](abc) = TERN[173](cab)
TERN[218](abc) = TERN[188](acb)
TERN[219](abc) = TERN[189](acb)
TERN[220](abc) = TERN[174](cab)
TERN[221](abc) = TERN[175](cab)
TERN[222](abc) = TERN[190](acb)
TERN[223](abc) = TERN[191](acb)
TERN[224](abc) = TERN[168](cba)
TERN[225](abc) = TERN[169](cba)
TERN[226](abc) = TERN[172](bca)
TERN[227](abc) = TERN[173](bca)
TERN[228](abc) = TERN[172](cba)
TERN[229](abc) = TERN[173](cba)
TERN[230](abc) = TERN[188](cba)
TERN[231](abc) = TERN[189](cba)
TERN[236](abc) = TERN[234](acb)
TERN[237](abc) = TERN[235](acb)
TERN[240](abc) = TERN[170](cba)
TERN[241](abc) = TERN[171](cba)
TERN[242](abc) = TERN[174](bca)
TERN[243](abc) = TERN[175](bca)
TERN[244](abc) = TERN[174](cba)
TERN[245](abc) = TERN[175](cba)
TERN[246](abc) = TERN[190](cba)
TERN[247](abc) = TERN[191](cba)
TERN[248](abc) = TERN[234](cba)
TERN[249](abc) = TERN[235](cba)
TERN[250](abc) = TERN[238](bac)
TERN[251](abc) = TERN[239](bac)
TERN[252](abc) = TERN[238](cba)
TERN[253](abc) = TERN[239](cba)
WojciechMula commented 6 years ago

I didn't consider this trait. Do you think it wouldn't impact on performance? Does a compiler always inline a call?

HJLebbink commented 6 years ago

ICC18 does not automatically inline in my code. I added a __forceinline to the signature to ensure the call is indeed inlined.

template<> __forceinline __m128i ternary<0x04>(const __m128i A, const __m128i B, const __m128i C)

And I call these methods from a large case-switch to get rid to the template variable.

forceinline m512i ternary(const m512i a, const m512i b, const __m512i c, const int i) { switch (i) { case 0: return _mm512_ternarylogic_epi64(a, b, c, 0); case 1: return _mm512_ternarylogic_epi64(a, b, c, 1); case 2: return _mm512_ternarylogic_epi64(a, b, c, 2); case 3: return ternary(a, c, b, 2); case 4: return ternary(a, c, b, 3); ...

This allows the compiler to optimize further, but those optimizations may be specific to my application (in which I brute-force search all combinations of vpternlogs).

I may be relevant for your project simply because you now only need to curate 80 functions instead of 256.

WojciechMula commented 6 years ago

I should have known it when I was manually optimizing functions. :) Now the number of functions is irrelevant as all optimizations are performed by scripts.

Could you please elaborate more about your application? If you don't like to share it here, feel free to write me email at wojciech_mula@poczta.onet.pl.

HJLebbink commented 6 years ago

See this question on StackOverflow on why I'm studying the vpternlog instruction. I've gitted the file ternary_logic.cpp in my fork of this code. This file contains convenience methods that you may find handy or that you could add to your code.