148 lines
4.2 KiB
C++
148 lines
4.2 KiB
C++
#include "PPintrin.h"
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
|
|
// implementation of absSerial(), but it is vectorized using PP intrinsics
|
|
void absVector(float *values, float *output, int N)
|
|
{
|
|
__pp_vec_float x;
|
|
__pp_vec_float result;
|
|
__pp_vec_float zero = _pp_vset_float(0.f);
|
|
__pp_mask maskAll, maskIsNegative, maskIsNotNegative;
|
|
|
|
// Note: Take a careful look at this loop indexing. This example
|
|
// code is not guaranteed to work when (N % VECTOR_WIDTH) != 0.
|
|
// Why is that the case?
|
|
for (int i = 0; i < N; i += VECTOR_WIDTH)
|
|
{
|
|
|
|
// All ones
|
|
maskAll = _pp_init_ones();
|
|
|
|
// All zeros
|
|
maskIsNegative = _pp_init_ones(0);
|
|
|
|
// Load vector of values from contiguous memory addresses
|
|
_pp_vload_float(x, values + i, maskAll); // x = values[i];
|
|
|
|
// Set mask according to predicate
|
|
_pp_vlt_float(maskIsNegative, x, zero, maskAll); // if (x < 0) {
|
|
|
|
// Execute instruction using mask ("if" clause)
|
|
_pp_vsub_float(result, zero, x, maskIsNegative); // output[i] = -x;
|
|
|
|
// Inverse maskIsNegative to generate "else" mask
|
|
maskIsNotNegative = _pp_mask_not(maskIsNegative); // } else {
|
|
|
|
// Execute instruction ("else" clause)
|
|
_pp_vload_float(result, values + i, maskIsNotNegative); // output[i] = x; }
|
|
|
|
// Write results back to memory
|
|
_pp_vstore_float(output + i, result, maskAll);
|
|
}
|
|
}
|
|
|
|
void clampedExpVector(float *values, int *exponents, float *output, int N)
|
|
{
|
|
//
|
|
// PP STUDENTS TODO: Implement your vectorized version of
|
|
// clampedExpSerial() here.
|
|
//
|
|
// Your solution should work for any value of
|
|
// N and VECTOR_WIDTH, not just when VECTOR_WIDTH divides N
|
|
//
|
|
__pp_vec_float x;
|
|
__pp_vec_int y;
|
|
__pp_vec_float result;
|
|
__pp_vec_int zero = _pp_vset_int(0);
|
|
__pp_vec_float cap = _pp_vset_float(9.999999f);
|
|
__pp_vec_int one = _pp_vset_int(1);
|
|
__pp_mask maskAll, maskNonZero, maskGreater;
|
|
maskAll = _pp_init_ones();
|
|
|
|
for (int i = 0; i < N; i += VECTOR_WIDTH)
|
|
{
|
|
if (i + VECTOR_WIDTH > N) {
|
|
float *tmp = new float[VECTOR_WIDTH];
|
|
for (int j = 0; i + j < N; j++)
|
|
tmp[j] = values[i+j];
|
|
for (int j = N % VECTOR_WIDTH; j < VECTOR_WIDTH; j++)
|
|
tmp[j] = 0;
|
|
_pp_vload_float(x, tmp, maskAll);
|
|
delete []tmp;
|
|
} else {
|
|
_pp_vload_float(x, values + i, maskAll); // x = values[i];
|
|
}
|
|
|
|
if (i + VECTOR_WIDTH > N) {
|
|
int *tmp = new int[VECTOR_WIDTH];
|
|
for (int j = 0; i + j < N; j++)
|
|
tmp[j] = exponents[i+j];
|
|
for (int j = N % VECTOR_WIDTH; j < VECTOR_WIDTH; j++)
|
|
tmp[j] = 0;
|
|
_pp_vload_int(y, tmp, maskAll);
|
|
delete []tmp;
|
|
} else {
|
|
_pp_vload_int(y, exponents + i, maskAll); // y = exponents[i];
|
|
}
|
|
|
|
cout << "min exponents: " << *min_element(y.value, y.value+VECTOR_WIDTH) << endl;
|
|
cout << "max exponents: " << *max_element(y.value, y.value+VECTOR_WIDTH) << endl;
|
|
|
|
_pp_vset_float(result, 1.f, maskAll);
|
|
maskNonZero = _pp_init_ones();
|
|
while (_pp_cntbits(maskNonZero) > 0) {
|
|
_pp_veq_int(maskNonZero, y, zero, maskAll);
|
|
maskNonZero = _pp_mask_not(maskNonZero);
|
|
|
|
_pp_vmult_float(result, result, x, maskNonZero);
|
|
_pp_vsub_int(y, y, one, maskNonZero);
|
|
}
|
|
|
|
_pp_vgt_float(maskGreater, result, cap, maskAll);
|
|
_pp_vset_float(result, 9.999999f, maskGreater);
|
|
|
|
if (i + VECTOR_WIDTH > N) {
|
|
float *tmp = new float[VECTOR_WIDTH];
|
|
_pp_vstore_float(tmp, result, maskAll);
|
|
for (int j = 0; i + j < N; j++)
|
|
output[i+j] = tmp[j];
|
|
delete []tmp;
|
|
} else {
|
|
_pp_vstore_float(output + i, result, maskAll);
|
|
}
|
|
}
|
|
}
|
|
|
|
// returns the sum of all elements in values
|
|
// You can assume N is a multiple of VECTOR_WIDTH
|
|
// You can assume VECTOR_WIDTH is a power of 2
|
|
float arraySumVector(float *values, int N)
|
|
{
|
|
|
|
//
|
|
// PP STUDENTS TODO: Implement your vectorized version of arraySumSerial here
|
|
//
|
|
__pp_vec_float x;
|
|
__pp_mask maskAll;
|
|
maskAll = _pp_init_ones();
|
|
|
|
float total = 0.f;
|
|
for (int i = 0; i < N; i += VECTOR_WIDTH)
|
|
{
|
|
_pp_vload_float(x, values + i, maskAll);
|
|
|
|
for (int n = VECTOR_WIDTH; n > 1; n >>= 1) {
|
|
_pp_hadd_float(x, x);
|
|
_pp_interleave_float(x, x);
|
|
}
|
|
|
|
float *tmp = new float[VECTOR_WIDTH];
|
|
_pp_vstore_float(tmp, x, maskAll);
|
|
total += tmp[0];
|
|
delete []tmp;
|
|
}
|
|
|
|
return total;
|
|
}
|