// Philox RNG for Xeon Phi cards __forceinline void philox2x32_mic(uint64_t counter, uint32_t key, __m512i& rnd1, __m512i& rnd2) { #ifdef __MIC__ const __m512i m = _mm512_set1_epi32(0xD256D193); const __m512i w = _mm512_set1_epi32(0x9E3779B9); const __m512i incr = _mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); __m512i r = _mm512_set1_epi32(counter & 0xFFFFFFFF); __m512i l = _mm512_set1_epi32(counter >> 32); __m512i keyV = _mm512_set1_epi32(key); keyV = _mm512_add_epi32(keyV, incr); #pragma unroll(10) for(int i = 0; i < 10; ++i) { __m512i l_old = l; l = _mm512_mullo_epi32(r, m); r = _mm512_xor_epi32(_mm512_xor_epi32(_mm512_mulhi_epu32(r, m), keyV), l_old); keyV = _mm512_add_epi32(keyV, w); } rnd1 = r; rnd2 = l; #endif }
inline void mic_sincos_ps(mic_m512_t x, mic_m512_t *s, mic_m512_t *c) { __m512i sign_bit = _mm512_and_epi32(_mm512_castps_si512(x), _pi32_sign_mask); x = _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(x), _pi32_inv_sign_mask)); mic_m512_t y = _mm512_mul_ps(x, _ps_cephes_FOPI); __m512i emm2 = _mm512_cvtfxpnt_round_adjustps_epi32(y, _MM_FROUND_TO_NEAREST_INT, _MM_EXPADJ_NONE); emm2 = _mm512_add_epi32(emm2, _pi32_1); emm2 = _mm512_and_epi32(emm2, _pi32_inv1); y = _mm512_cvtfxpnt_round_adjustepu32_ps(emm2, _MM_FROUND_TO_NEAREST_INT, _MM_EXPADJ_NONE); __m512i cos_emm2 = _mm512_sub_epi32(emm2, _pi32_2); __m512i emm0 = _mm512_and_epi32(emm2, _pi32_4); __m512i cos_emm0 = _mm512_andnot_epi32(cos_emm2, _pi32_4); emm0 = _mm512_slli_epi32(emm0, 29); cos_emm0 = _mm512_slli_epi32(cos_emm0, 29); sign_bit = _mm512_xor_epi32(sign_bit, emm0); emm2 = _mm512_and_epi32(emm2, _pi32_2); cos_emm2 = _mm512_and_epi32(cos_emm2, _pi32_2); __mmask16 mask = _mm512_cmp_epi32_mask(emm2, _pi32_0, _MM_CMPINT_EQ); emm2 = _mm512_mask_add_epi32(_pi32_0, mask, _pi32_ffff, _pi32_0); __mmask16 cos_mask = _mm512_cmp_epi32_mask(cos_emm2, _pi32_0, _MM_CMPINT_EQ); cos_emm2 = _mm512_mask_add_epi32(_pi32_0, cos_mask, _pi32_ffff, _pi32_0); x = _mm512_fmadd_ps(y, _ps_minus_cephes_DP123, x); mic_m512_t x2 = _mm512_mul_ps(x, x); mic_m512_t x3 = _mm512_mul_ps(x2, x); mic_m512_t x4 = _mm512_mul_ps(x2, x2); y = _mm512_fmadd_ps(_ps_coscof_p0, x2, _ps_coscof_p1); y = _mm512_fmadd_ps(y, x2, _ps_coscof_p2); mic_m512_t temp_2 = _mm512_fmsub_ps(x2, _ps_0point5, _ps_1); y = _mm512_fmsub_ps(y, x4, temp_2); mic_m512_t y2 = _mm512_fmadd_ps(_ps_sincof_p0, x2, _ps_sincof_p1); y2 = _mm512_fmadd_ps(y2, x2, _ps_sincof_p2); y2 = _mm512_fmadd_ps(y2, x3, x); mic_m512_t cos_y = y; mic_m512_t cos_y2 = y2; y = _mm512_castsi512_ps(_mm512_andnot_epi32(emm2, _mm512_castps_si512(y))); cos_y = _mm512_castsi512_ps(_mm512_andnot_epi32(cos_emm2, _mm512_castps_si512(cos_y))); y2 = _mm512_castsi512_ps(_mm512_and_epi32(emm2, _mm512_castps_si512(y2))); cos_y2 = _mm512_castsi512_ps(_mm512_and_epi32(cos_emm2, _mm512_castps_si512(cos_y2))); y = _mm512_add_ps(y, y2); cos_y = _mm512_add_ps(cos_y, cos_y2); *s = _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(y), sign_bit)); *c = _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(cos_y), cos_emm0)); } // sincos_ps()
// sin() static inline mic_m512_t mic_sin_ps(mic_m512_t x) { __m512i sign_bit; sign_bit = _mm512_and_epi32(_mm512_castps_si512(x), _pi32_sign_mask); x = _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(x), _pi32_inv_sign_mask)); mic_m512_t y = _mm512_mul_ps(x, _ps_cephes_FOPI); __m512i emm2 = _mm512_cvtfxpnt_round_adjustps_epi32(y, _MM_FROUND_TO_NEAREST_INT, _MM_EXPADJ_NONE); emm2 = _mm512_add_epi32(emm2, _pi32_1); emm2 = _mm512_and_epi32(emm2, _pi32_inv1); y = _mm512_cvtfxpnt_round_adjustepu32_ps(emm2, _MM_FROUND_TO_NEAREST_INT, _MM_EXPADJ_NONE); __m512i emm0 = _mm512_and_epi32(emm2, _pi32_4); emm0 = _mm512_slli_epi32(emm0, 29); emm2 = _mm512_and_epi32(emm2, _pi32_2); __mmask16 mask = _mm512_cmp_epi32_mask(emm2, _pi32_0, _MM_CMPINT_EQ); emm2 = _mm512_mask_add_epi32(_pi32_0, mask, _pi32_ffff, _pi32_0); sign_bit = _mm512_xor_epi32(sign_bit, emm0); mic_m512_t temp = _ps_minus_cephes_DP123; temp = _mm512_mul_ps(y, temp); x = _mm512_add_ps(x, temp); mic_m512_t x2 = _mm512_mul_ps(x, x); mic_m512_t x3 = _mm512_mul_ps(x2, x); mic_m512_t x4 = _mm512_mul_ps(x2, x2); y = _mm512_mul_ps(_ps_coscof_p0, x2); mic_m512_t y2 = _mm512_mul_ps(_ps_sincof_p0, x2); y = _mm512_add_ps(y, _ps_coscof_p1); y2 = _mm512_add_ps(y2, _ps_sincof_p1); y = _mm512_mul_ps(y, x2); y2 = _mm512_mul_ps(y2, x2); y = _mm512_add_ps(y, _ps_coscof_p2); y2 = _mm512_add_ps(y2, _ps_sincof_p2); y = _mm512_mul_ps(y, x4); y2 = _mm512_mul_ps(y2, x3); temp = _mm512_mul_ps(x2, _ps_0point5); temp = _mm512_sub_ps(temp, _ps_1); y = _mm512_sub_ps(y, temp); y2 = _mm512_add_ps(y2, x); y = _mm512_castsi512_ps(_mm512_andnot_epi32(emm2, _mm512_castps_si512(y))); y2 = _mm512_castsi512_ps(_mm512_and_epi32(emm2, _mm512_castps_si512(y2))); y = _mm512_add_ps(y, y2); y = _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(y), sign_bit)); return y; } // sin_ps()
inline static int16_t smith_waterman_farrar(Objeto*o, char *sec_database, int16_t long_sec_database){ int32_t * aux_Max; int16_t ret_max = 0; __m512i vGapOpen, vGapExtend, zero; __m512i vF, vH, vMax, vE_j, vAux0; int segLen = (64 / sizeof(int32_t)); int numSeg = (long_sec_ref + 63 / sizeof(int32_t)) / (64 / sizeof(int32_t)); int32_t cog[segLen] __attribute__((aligned(64))); int32_t ceg[segLen] __attribute__((aligned(64))); // for(int x=0;x<segLen;x++) { cog[x] = coste_open_gap; ceg[x] = coste_extend_gap; } vGapOpen = _mm512_load_epi32(cog); vGapExtend = _mm512_load_epi32(ceg); zero = _mm512_xor_epi32(zero, zero); vMax = _mm512_xor_epi32(vMax, vMax); // vMax = <0, 0, ..., 0> for(int j=0; j<long_profile; j++){ o->columnaPrevia_Max[j] = 0; //o->columna_Up[j] = 0; o->columna_Left[j] = 0; } for(int x=0; x<long_sec_database; x++){ // vF = <0, 0, ..., 0> vF = _mm512_xor_epi32(vF, vF); // vH = vHStore[numSeg - 1] << 1 vH = _mm512_load_epi32(o->columnaPrevia_Max + (numSeg - 1) * segLen); vH = shiftRight(vH); // int8_t pos_letra_database = letras[(int)(sec_database[x])]; //printf("Letra %d %c %d\n", x, sec_database[x], pos_letra_database); int32_t offset = pos_letra_database * long_profile; int j; for(j=0; j<numSeg; j++){ // vH = vH + vProfile[letra][j] int32_t * valor_match = profile + offset; offset += segLen; vAux0 = _mm512_load_epi32(valor_match); vH = _mm512_add_epi32(vH, vAux0); // vMax = max(vMax, vH); vMax = _mm512_max_epi32(vMax, vH); // vE[j] = max(vH, vE[j]) // vH = max(vH, vF) vE_j = _mm512_load_epi32(o->columna_Left + j*segLen); vH = _mm512_max_epi32(vH, vE_j); vH = _mm512_max_epi32(vH, vF); // vHStore[j] = vH _mm512_store_epi32(o->columnaActual_Max + j*segLen, vH); // vAux = vH - vGapOpen vAux0 = _mm512_sub_epi32(vH, vGapOpen); vAux0 = _mm512_max_epi32(vAux0, zero); // vE[j] = vE[j] - vGapExtend vE_j = _mm512_sub_epi32(vE_j, vGapExtend); vE_j = _mm512_max_epi32(vE_j, zero); // vE[j] = max(vE[j], vAux) vE_j = _mm512_max_epi32(vE_j, vAux0); _mm512_store_epi32(o->columna_Left + j*segLen, vE_j); // vF = vF - vGapExtend vF = _mm512_sub_epi32(vF, vGapExtend); vF = _mm512_max_epi32(vF, zero); // vF = max(vF, vAux) vF = _mm512_max_epi32(vF, vAux0); // vH = vHLoad[j] vH = _mm512_load_epi32(o->columnaPrevia_Max + j*segLen); } // Optimización de SWAT /* for(int x=0; x<long_profile; x++){ printf("vMax[%d]=%d\n", x, o->columnaActual_Max[x]); } printf("Numseg: %d\n", numSeg); displayV("F", vF); */ // vF = vF << 1 vF = shiftRight(vF); j = 0; do { // while(AnyElement(vF > vHStore[j] - vGapOpen vH = _mm512_load_epi32(o->columnaActual_Max + j*segLen); vAux0 = _mm512_sub_epi32(vH, vGapOpen); vAux0 = _mm512_max_epi32(vAux0, zero); __mmask16 mascara = _mm512_cmpgt_epi32_mask (vF, vAux0); if (mascara == 0) break; // vHStore[j] = max(vHStore[j], vF) vH = _mm512_max_epi32(vH, vF); _mm512_store_epi32(o->columnaActual_Max + j*segLen, vH); // vF = vF - vGapExtend vF = _mm512_sub_epi32(vF, vGapExtend); vF = _mm512_max_epi32(vF, zero); if (++j >= numSeg) { // vF = vF << 1 vF = shiftRight(vF); j = 0; } } while(1); // aux_Max = o->columnaActual_Max; o->columnaActual_Max = o->columnaPrevia_Max; o->columnaPrevia_Max = aux_Max; // } int32_t max[segLen] __attribute__((aligned(64))); _mm512_store_epi32(max, vMax); for(int x=1;x<segLen;x++) { if(max[0] < max[x]) max[0] = max[x]; } if (max[0] > 32767) max[0] = 32767; ret_max = max[0]; return ret_max; }