// 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()
// exp() inline mic_m512_t mic_exp_ps(mic_m512_t x) { x = _mm512_min_ps(x, _ps_exp_hi); x = _mm512_max_ps(x, _ps_exp_lo); mic_m512_t temp_2 = _mm512_fmadd_ps(x, _ps_cephes_LOG2EF, _ps_0point5); mic_m512_t temp_1 = _mm512_round_ps(temp_2, _MM_FROUND_TO_NEAREST_INT, _MM_EXPADJ_NONE); mic_m512_t temp_3 = _mm512_sub_ps(temp_1, temp_2); __mmask16 mask = _mm512_cmp_ps_mask(temp_3, _ps_0, _MM_CMPINT_GT); temp_2 = _mm512_mask_sub_ps(temp_1, mask, temp_1, _ps_1); __m512i emm0 = _mm512_cvtfxpnt_round_adjustps_epi32(temp_2, _MM_FROUND_TO_NEAREST_INT, _MM_EXPADJ_NONE); x = _mm512_fnmadd_ps(temp_2, _ps_cephes_exp_C12, 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); temp_1 = _mm512_add_ps(x, _ps_1); temp_1 = _mm512_fmadd_ps(x2, _ps_cephes_exp_p5, temp_1); temp_1 = _mm512_fmadd_ps(x3, _ps_cephes_exp_p4, temp_1); temp_2 = _mm512_mul_ps(x3, _ps_cephes_exp_p0); temp_3 = _mm512_mul_ps(x2, _ps_cephes_exp_p1); mic_m512_t temp_4 = _mm512_mul_ps(x, _ps_cephes_exp_p2); emm0 = _mm512_add_epi32(emm0, _pi32_0x7f); temp_2 = _mm512_add_ps(temp_2, temp_3); temp_3 = _mm512_add_ps(temp_3, temp_4); temp_2 = _mm512_add_ps(temp_2, temp_3); emm0 = _mm512_slli_epi32(emm0, 23); mic_m512_t pow2n = _mm512_castsi512_ps(emm0); temp_2 = _mm512_mul_ps(temp_2, x4); mic_m512_t y = _mm512_add_ps(temp_1, temp_2); y = _mm512_mul_ps(y, pow2n); return y; } // newexp_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; }
int main(int argc, char **argv) { int w, h, bit_num = 0; char byte_acc = 0; long byte_total = 0; int i, iter = 50; double x, y, limit = 2.0; double Zr, Zi, Cr, Ci, Tr, Ti; w = h = argc > 1 ? atoi(argv[1]) : 32000; printf("P4\n%d %d\n", w, h); #ifdef USEAVX512 __m512i a = _mm512_set1_epi32(0); __m512i b = _mm512_set1_epi32(1); __m512i t; #endif for (y = 0; y < h; ++y) { #ifdef USEAVX512 t = a; a = b; #ifdef USEHEAVYAVX512 b = _mm512_mul_epi32(b, t); #else b = _mm512_add_epi32(b, t); #endif #endif for (x = 0; x < w; ++x) { Zr = Zi = Tr = Ti = 0.0; Cr = (2.0 * x / w - 1.5); Ci = (2.0 * y / h - 1.0); for (i = 0; i < iter && (Tr + Ti <= limit * limit); ++i) { Zi = 2.0 * Zr * Zi + Ci; Zr = Tr - Ti + Cr; Tr = Zr * Zr; Ti = Zi * Zi; } byte_acc <<= 1; if (Tr + Ti <= limit * limit) byte_acc |= 0x01; ++bit_num; if (bit_num == 8) { byte_total += byte_acc; // putc(byte_acc,stdout); byte_acc = 0; bit_num = 0; } else if (x == w - 1) { byte_acc <<= (8 - w % 8); byte_total += byte_acc; // putc(byte_acc,stdout); byte_acc = 0; bit_num = 0; } } } #ifdef USEAVX512 printf("we used avx512 %d \n", _mm256_extract_epi32(_mm512_extracti64x4_epi64(b, 1), 7)); #else printf("we did not use avx512\n"); #endif return byte_total; }