\brief get the error metrics \param y the output value, 256-bits, 8xbf16 \param y_ref the reference value, 256-bits, 8xbf16 \return the error metrics
| 31 | /// \param y_ref the reference value, 256-bits, 8xbf16 |
| 32 | /// \return the error metrics |
| 33 | inline error_metrics get_error_metrics(buffer<bf16>& y, buffer<bf16>& y_ref){ |
| 34 | assert(y.size() == y_ref.size()); |
| 35 | error_metrics metrics; |
| 36 | const int simd_width = 8; |
| 37 | |
| 38 | __m256 dot_product = _mm256_setzero_ps(); |
| 39 | __m256 y_square_sum = _mm256_setzero_ps(); |
| 40 | __m256 y_ref_square_sum = _mm256_setzero_ps(); |
| 41 | __m256 error_square_sum = _mm256_setzero_ps(); |
| 42 | __m256 abs_error_sum = _mm256_setzero_ps(); |
| 43 | __m256 abs_y_ref_sum = _mm256_setzero_ps(); |
| 44 | for (int i = 0; i < y.size(); i += simd_width){ |
| 45 | __m128i y_bf16 = _mm_loadu_si128((__m128i*)(y.data() + i)); |
| 46 | __m128i y_ref_bf16 = _mm_loadu_si128((__m128i*)(y_ref.data() + i)); |
| 47 | __m256 y_vec = bf16o_fp32(y_bf16); |
| 48 | __m256 y_ref_vec = bf16o_fp32(y_ref_bf16); |
| 49 | __m256 error_vec = _mm256_sub_ps(y_vec, y_ref_vec); |
| 50 | y_square_sum = _mm256_add_ps(y_square_sum, _mm256_mul_ps(y_vec, y_vec)); |
| 51 | y_ref_square_sum = _mm256_add_ps(y_ref_square_sum, _mm256_mul_ps(y_ref_vec, y_ref_vec)); |
| 52 | dot_product = _mm256_add_ps(dot_product, _mm256_mul_ps(y_vec, y_ref_vec)); |
| 53 | error_square_sum = _mm256_add_ps(error_square_sum, _mm256_mul_ps(error_vec, error_vec)); |
| 54 | abs_error_sum = _mm256_add_ps(abs_error_sum, _mm256_abs_ps(error_vec)); |
| 55 | abs_y_ref_sum = _mm256_add_ps(abs_y_ref_sum, _mm256_abs_ps(y_ref_vec)); |
| 56 | } |
| 57 | f32 temp[simd_width]; |
| 58 | _mm256_storeu_ps(temp, dot_product); |
| 59 | f32 dot_product_sum = temp[0] + temp[1] + temp[2] + temp[3] + |
| 60 | temp[4] + temp[5] + temp[6] + temp[7]; |
| 61 | _mm256_storeu_ps(temp, y_square_sum); |
| 62 | f32 y_square_sum_sum = temp[0] + temp[1] + temp[2] + temp[3] + |
| 63 | temp[4] + temp[5] + temp[6] + temp[7]; |
| 64 | _mm256_storeu_ps(temp, y_ref_square_sum); |
| 65 | f32 y_ref_square_sum_sum = temp[0] + temp[1] + temp[2] + temp[3] + |
| 66 | temp[4] + temp[5] + temp[6] + temp[7]; |
| 67 | _mm256_storeu_ps(temp, error_square_sum); |
| 68 | f32 error_square_sum_sum = temp[0] + temp[1] + temp[2] + temp[3] + |
| 69 | temp[4] + temp[5] + temp[6] + temp[7]; |
| 70 | _mm256_storeu_ps(temp, abs_error_sum); |
| 71 | f32 abs_error_sum_sum = temp[0] + temp[1] + temp[2] + temp[3] + |
| 72 | temp[4] + temp[5] + temp[6] + temp[7]; |
| 73 | _mm256_storeu_ps(temp, abs_y_ref_sum); |
| 74 | f32 abs_y_ref_sum_sum = temp[0] + temp[1] + temp[2] + temp[3] + |
| 75 | temp[4] + temp[5] + temp[6] + temp[7]; |
| 76 | |
| 77 | // Cosine Similarity |
| 78 | float cosine_similarity = dot_product_sum / (sqrt(y_square_sum_sum) * sqrt(y_ref_square_sum_sum)); |
| 79 | // Relative L1 |
| 80 | float relative_l1 = abs_error_sum_sum / abs_y_ref_sum_sum; |
| 81 | // RMSE |
| 82 | float rmse = sqrt(error_square_sum_sum / y.size()); |
| 83 | // Relative L2 |
| 84 | float relative_l2 = sqrt(error_square_sum_sum / y_ref_square_sum_sum); |
| 85 | metrics.CosineSimilarity = cosine_similarity; |
| 86 | metrics.RelativeL1 = relative_l1; |
| 87 | metrics.RMSE = rmse; |
| 88 | metrics.RelativeL2 = relative_l2; |
| 89 | return metrics; |
| 90 | } |