init: HW1
This commit is contained in:
commit
a6479e729f
19 files changed
+1197
No files matched your search
@@ -0,0 +1,20 @@
|
||||
CXX := g++
|
||||
CXXFLAGS := -O3 -std=c++17 -Wall
|
||||
|
||||
ifneq ($(VECTOR_WIDTH),)
|
||||
CXXFLAGS += -DVECTOR_WIDTH=$(VECTOR_WIDTH)
|
||||
endif
|
||||
|
||||
all: myexp
|
||||
|
||||
logger.o: logger.cpp logger.h PPintrin.h PPintrin.cpp def.h
|
||||
$(CXX) $(CXXFLAGS) -c logger.cpp
|
||||
|
||||
PPintrin.o: PPintrin.cpp PPintrin.h logger.cpp logger.h def.h
|
||||
$(CXX) $(CXXFLAGS) -c PPintrin.cpp
|
||||
|
||||
myexp: PPintrin.o logger.o main.cpp serialOP.cpp vectorOP.cpp
|
||||
$(CXX) $(CXXFLAGS) logger.o PPintrin.o main.cpp serialOP.cpp vectorOP.cpp -o myexp
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.s myexp *~
|
||||
@@ -0,0 +1,304 @@
|
||||
#include "PPintrin.h"
|
||||
#include "logger.h"
|
||||
|
||||
//******************
|
||||
//* Implementation *
|
||||
//******************
|
||||
|
||||
__pp_mask _pp_init_ones(int first)
|
||||
{
|
||||
__pp_mask mask;
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
mask.value[i] = (i < first) ? true : false;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
__pp_mask _pp_mask_not(__pp_mask &maska)
|
||||
{
|
||||
__pp_mask resultMask;
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
resultMask.value[i] = !maska.value[i];
|
||||
}
|
||||
PPLogger.addLog("masknot", _pp_init_ones(), VECTOR_WIDTH);
|
||||
return resultMask;
|
||||
}
|
||||
|
||||
__pp_mask _pp_mask_or(__pp_mask &maska, __pp_mask &maskb)
|
||||
{
|
||||
__pp_mask resultMask;
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
resultMask.value[i] = maska.value[i] | maskb.value[i];
|
||||
}
|
||||
PPLogger.addLog("maskor", _pp_init_ones(), VECTOR_WIDTH);
|
||||
return resultMask;
|
||||
}
|
||||
|
||||
__pp_mask _pp_mask_and(__pp_mask &maska, __pp_mask &maskb)
|
||||
{
|
||||
__pp_mask resultMask;
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
resultMask.value[i] = maska.value[i] && maskb.value[i];
|
||||
}
|
||||
PPLogger.addLog("maskand", _pp_init_ones(), VECTOR_WIDTH);
|
||||
return resultMask;
|
||||
}
|
||||
|
||||
int _pp_cntbits(__pp_mask &maska)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
if (maska.value[i])
|
||||
count++;
|
||||
}
|
||||
PPLogger.addLog("cntbits", _pp_init_ones(), VECTOR_WIDTH);
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void _pp_vset(__pp_vec<T> &vecResult, T value, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
vecResult.value[i] = mask.value[i] ? value : vecResult.value[i];
|
||||
}
|
||||
PPLogger.addLog("vset", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vset<float>(__pp_vec_float &vecResult, float value, __pp_mask &mask);
|
||||
template void _pp_vset<int>(__pp_vec_int &vecResult, int value, __pp_mask &mask);
|
||||
|
||||
void _pp_vset_float(__pp_vec_float &vecResult, float value, __pp_mask &mask) { _pp_vset<float>(vecResult, value, mask); }
|
||||
void _pp_vset_int(__pp_vec_int &vecResult, int value, __pp_mask &mask) { _pp_vset<int>(vecResult, value, mask); }
|
||||
|
||||
__pp_vec_float _pp_vset_float(float value)
|
||||
{
|
||||
__pp_vec_float vecResult;
|
||||
__pp_mask mask = _pp_init_ones();
|
||||
_pp_vset_float(vecResult, value, mask);
|
||||
return vecResult;
|
||||
}
|
||||
__pp_vec_int _pp_vset_int(int value)
|
||||
{
|
||||
__pp_vec_int vecResult;
|
||||
__pp_mask mask = _pp_init_ones();
|
||||
_pp_vset_int(vecResult, value, mask);
|
||||
return vecResult;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void _pp_vmove(__pp_vec<T> &dest, __pp_vec<T> &src, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
dest.value[i] = mask.value[i] ? src.value[i] : dest.value[i];
|
||||
}
|
||||
PPLogger.addLog("vmove", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vmove<float>(__pp_vec_float &dest, __pp_vec_float &src, __pp_mask &mask);
|
||||
template void _pp_vmove<int>(__pp_vec_int &dest, __pp_vec_int &src, __pp_mask &mask);
|
||||
|
||||
void _pp_vmove_float(__pp_vec_float &dest, __pp_vec_float &src, __pp_mask &mask) { _pp_vmove<float>(dest, src, mask); }
|
||||
void _pp_vmove_int(__pp_vec_int &dest, __pp_vec_int &src, __pp_mask &mask) { _pp_vmove<int>(dest, src, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_vload(__pp_vec<T> &dest, T *src, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
dest.value[i] = mask.value[i] ? src[i] : dest.value[i];
|
||||
}
|
||||
PPLogger.addLog("vload", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vload<float>(__pp_vec_float &dest, float *src, __pp_mask &mask);
|
||||
template void _pp_vload<int>(__pp_vec_int &dest, int *src, __pp_mask &mask);
|
||||
|
||||
void _pp_vload_float(__pp_vec_float &dest, float *src, __pp_mask &mask) { _pp_vload<float>(dest, src, mask); }
|
||||
void _pp_vload_int(__pp_vec_int &dest, int *src, __pp_mask &mask) { _pp_vload<int>(dest, src, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_vstore(T *dest, __pp_vec<T> &src, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
dest[i] = mask.value[i] ? src.value[i] : dest[i];
|
||||
}
|
||||
PPLogger.addLog("vstore", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vstore<float>(float *dest, __pp_vec_float &src, __pp_mask &mask);
|
||||
template void _pp_vstore<int>(int *dest, __pp_vec_int &src, __pp_mask &mask);
|
||||
|
||||
void _pp_vstore_float(float *dest, __pp_vec_float &src, __pp_mask &mask) { _pp_vstore<float>(dest, src, mask); }
|
||||
void _pp_vstore_int(int *dest, __pp_vec_int &src, __pp_mask &mask) { _pp_vstore<int>(dest, src, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_vadd(__pp_vec<T> &vecResult, __pp_vec<T> &veca, __pp_vec<T> &vecb, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
vecResult.value[i] = mask.value[i] ? (veca.value[i] + vecb.value[i]) : vecResult.value[i];
|
||||
}
|
||||
PPLogger.addLog("vadd", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vadd<float>(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
template void _pp_vadd<int>(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
void _pp_vadd_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask) { _pp_vadd<float>(vecResult, veca, vecb, mask); }
|
||||
void _pp_vadd_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_vadd<int>(vecResult, veca, vecb, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_vsub(__pp_vec<T> &vecResult, __pp_vec<T> &veca, __pp_vec<T> &vecb, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
vecResult.value[i] = mask.value[i] ? (veca.value[i] - vecb.value[i]) : vecResult.value[i];
|
||||
}
|
||||
PPLogger.addLog("vsub", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vsub<float>(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
template void _pp_vsub<int>(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
void _pp_vsub_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask) { _pp_vsub<float>(vecResult, veca, vecb, mask); }
|
||||
void _pp_vsub_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_vsub<int>(vecResult, veca, vecb, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_vmult(__pp_vec<T> &vecResult, __pp_vec<T> &veca, __pp_vec<T> &vecb, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
vecResult.value[i] = mask.value[i] ? (veca.value[i] * vecb.value[i]) : vecResult.value[i];
|
||||
}
|
||||
PPLogger.addLog("vmult", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vmult<float>(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
template void _pp_vmult<int>(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
void _pp_vmult_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask) { _pp_vmult<float>(vecResult, veca, vecb, mask); }
|
||||
void _pp_vmult_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_vmult<int>(vecResult, veca, vecb, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_vdiv(__pp_vec<T> &vecResult, __pp_vec<T> &veca, __pp_vec<T> &vecb, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
vecResult.value[i] = mask.value[i] ? (veca.value[i] / vecb.value[i]) : vecResult.value[i];
|
||||
}
|
||||
PPLogger.addLog("vdiv", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vdiv<float>(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
template void _pp_vdiv<int>(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
void _pp_vdiv_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask) { _pp_vdiv<float>(vecResult, veca, vecb, mask); }
|
||||
void _pp_vdiv_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_vdiv<int>(vecResult, veca, vecb, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_vabs(__pp_vec<T> &vecResult, __pp_vec<T> &veca, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
vecResult.value[i] = mask.value[i] ? (abs(veca.value[i])) : vecResult.value[i];
|
||||
}
|
||||
PPLogger.addLog("vabs", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vabs<float>(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_mask &mask);
|
||||
template void _pp_vabs<int>(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_mask &mask);
|
||||
|
||||
void _pp_vabs_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_mask &mask) { _pp_vabs<float>(vecResult, veca, mask); }
|
||||
void _pp_vabs_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_mask &mask) { _pp_vabs<int>(vecResult, veca, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_vgt(__pp_mask &maskResult, __pp_vec<T> &veca, __pp_vec<T> &vecb, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
maskResult.value[i] = mask.value[i] ? (veca.value[i] > vecb.value[i]) : maskResult.value[i];
|
||||
}
|
||||
PPLogger.addLog("vgt", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vgt<float>(__pp_mask &maskResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
template void _pp_vgt<int>(__pp_mask &maskResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
void _pp_vgt_float(__pp_mask &maskResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask) { _pp_vgt<float>(maskResult, veca, vecb, mask); }
|
||||
void _pp_vgt_int(__pp_mask &maskResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_vgt<int>(maskResult, veca, vecb, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_vlt(__pp_mask &maskResult, __pp_vec<T> &veca, __pp_vec<T> &vecb, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
maskResult.value[i] = mask.value[i] ? (veca.value[i] < vecb.value[i]) : maskResult.value[i];
|
||||
}
|
||||
PPLogger.addLog("vlt", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_vlt<float>(__pp_mask &maskResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
template void _pp_vlt<int>(__pp_mask &maskResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
void _pp_vlt_float(__pp_mask &maskResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask) { _pp_vlt<float>(maskResult, veca, vecb, mask); }
|
||||
void _pp_vlt_int(__pp_mask &maskResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_vlt<int>(maskResult, veca, vecb, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_veq(__pp_mask &maskResult, __pp_vec<T> &veca, __pp_vec<T> &vecb, __pp_mask &mask)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
maskResult.value[i] = mask.value[i] ? (veca.value[i] == vecb.value[i]) : maskResult.value[i];
|
||||
}
|
||||
PPLogger.addLog("veq", mask, VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_veq<float>(__pp_mask &maskResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
template void _pp_veq<int>(__pp_mask &maskResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
void _pp_veq_float(__pp_mask &maskResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask) { _pp_veq<float>(maskResult, veca, vecb, mask); }
|
||||
void _pp_veq_int(__pp_mask &maskResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_veq<int>(maskResult, veca, vecb, mask); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_hadd(__pp_vec<T> &vecResult, __pp_vec<T> &vec)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH / 2; i++)
|
||||
{
|
||||
T result = vec.value[2 * i] + vec.value[2 * i + 1];
|
||||
vecResult.value[2 * i] = result;
|
||||
vecResult.value[2 * i + 1] = result;
|
||||
}
|
||||
PPLogger.addLog("hadd", _pp_init_ones(), VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_hadd<float>(__pp_vec_float &vecResult, __pp_vec_float &vec);
|
||||
|
||||
void _pp_hadd_float(__pp_vec_float &vecResult, __pp_vec_float &vec) { _pp_hadd<float>(vecResult, vec); }
|
||||
|
||||
template <typename T>
|
||||
void _pp_interleave(__pp_vec<T> &vecResult, __pp_vec<T> vec)
|
||||
{
|
||||
for (int i = 0; i < VECTOR_WIDTH; i++)
|
||||
{
|
||||
int index = i < VECTOR_WIDTH / 2 ? (2 * i) : (2 * (i - VECTOR_WIDTH / 2) + 1);
|
||||
vecResult.value[i] = vec.value[index];
|
||||
}
|
||||
PPLogger.addLog("interleave", _pp_init_ones(), VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
template void _pp_interleave<float>(__pp_vec_float &vecResult, __pp_vec_float vec);
|
||||
|
||||
void _pp_interleave_float(__pp_vec_float &vecResult, __pp_vec_float vec) { _pp_interleave<float>(vecResult, vec); }
|
||||
|
||||
void addUserLog(const char *logStr)
|
||||
{
|
||||
PPLogger.addLog(logStr, _pp_init_ones(), 0);
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
#ifndef PPINTRIN_H_
|
||||
#define PPINTRIN_H_
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include "logger.h"
|
||||
#include "def.h"
|
||||
//*******************
|
||||
//* Type Definition *
|
||||
//*******************
|
||||
|
||||
extern Logger PPLogger;
|
||||
|
||||
template <typename T>
|
||||
struct __pp_vec {
|
||||
T value[VECTOR_WIDTH];
|
||||
};
|
||||
|
||||
// Declare a mask with __pp_mask
|
||||
struct __pp_mask : __pp_vec<bool> {};
|
||||
|
||||
// Declare a floating point vector register with __pp_vec_float
|
||||
#define __pp_vec_float __pp_vec<float>
|
||||
|
||||
// Declare an integer vector register with __pp_vec_int
|
||||
#define __pp_vec_int __pp_vec<int>
|
||||
|
||||
//***********************
|
||||
//* Function Definition *
|
||||
//***********************
|
||||
|
||||
// Return a mask initialized to 1 in the first N lanes and 0 in the others
|
||||
__pp_mask _pp_init_ones(int first = VECTOR_WIDTH);
|
||||
|
||||
// Return the inverse of maska
|
||||
__pp_mask _pp_mask_not(__pp_mask &maska);
|
||||
|
||||
// Return (maska | maskb)
|
||||
__pp_mask _pp_mask_or(__pp_mask &maska, __pp_mask &maskb);
|
||||
|
||||
// Return (maska & maskb)
|
||||
__pp_mask _pp_mask_and(__pp_mask &maska, __pp_mask &maskb);
|
||||
|
||||
// Count the number of 1s in maska
|
||||
int _pp_cntbits(__pp_mask &maska);
|
||||
|
||||
// Set register to value if vector lane is active
|
||||
// otherwise keep the old value
|
||||
void _pp_vset_float(__pp_vec_float &vecResult, float value, __pp_mask &mask);
|
||||
void _pp_vset_int(__pp_vec_int &vecResult, int value, __pp_mask &mask);
|
||||
// For user's convenience, returns a vector register with all lanes initialized to value
|
||||
__pp_vec_float _pp_vset_float(float value);
|
||||
__pp_vec_int _pp_vset_int(int value);
|
||||
|
||||
// Copy values from vector register src to vector register dest if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vmove_float(__pp_vec_float &dest, __pp_vec_float &src, __pp_mask &mask);
|
||||
void _pp_vmove_int(__pp_vec_int &dest, __pp_vec_int &src, __pp_mask &mask);
|
||||
|
||||
// Load values from array src to vector register dest if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vload_float(__pp_vec_float &dest, float* src, __pp_mask &mask);
|
||||
void _pp_vload_int(__pp_vec_int &dest, int* src, __pp_mask &mask);
|
||||
|
||||
// Store values from vector register src to array dest if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vstore_float(float* dest, __pp_vec_float &src, __pp_mask &mask);
|
||||
void _pp_vstore_int(int* dest, __pp_vec_int &src, __pp_mask &mask);
|
||||
|
||||
// Return calculation of (veca + vecb) if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vadd_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
void _pp_vadd_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
// Return calculation of (veca - vecb) if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vsub_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
void _pp_vsub_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
// Return calculation of (veca * vecb) if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vmult_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
void _pp_vmult_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
// Return calculation of (veca / vecb) if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vdiv_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
void _pp_vdiv_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
|
||||
// Return calculation of absolute value abs(veca) if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vabs_float(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_mask &mask);
|
||||
void _pp_vabs_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_mask &mask);
|
||||
|
||||
// Return a mask of (veca > vecb) if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vgt_float(__pp_mask &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
void _pp_vgt_int(__pp_mask &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
// Return a mask of (veca < vecb) if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_vlt_float(__pp_mask &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
void _pp_vlt_int(__pp_mask &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
// Return a mask of (veca == vecb) if vector lane active
|
||||
// otherwise keep the old value
|
||||
void _pp_veq_float(__pp_mask &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask);
|
||||
void _pp_veq_int(__pp_mask &vecResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask);
|
||||
|
||||
// Adds up adjacent pairs of elements, so
|
||||
// [0 1 2 3] -> [0+1 0+1 2+3 2+3]
|
||||
void _pp_hadd_float(__pp_vec_float &vecResult, __pp_vec_float &vec);
|
||||
|
||||
// Performs an even-odd interleaving where all even-indexed elements move to front half
|
||||
// of the array and odd-indexed to the back half, so
|
||||
// [0 1 2 3 4 5 6 7] -> [0 2 4 6 1 3 5 7]
|
||||
void _pp_interleave_float(__pp_vec_float &vecResult, __pp_vec_float vec);
|
||||
|
||||
// Add a customized log to help debugging
|
||||
void addUserLog(const char * logStr);
|
||||
|
||||
#endif
|
||||
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
// Define vector unit width here
|
||||
#ifndef VECTOR_WIDTH
|
||||
#define VECTOR_WIDTH 4
|
||||
#endif
|
||||
#define EXP_MAX 10
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "logger.h"
|
||||
#include "PPintrin.h"
|
||||
|
||||
void Logger::addLog(const char *instruction, __pp_mask mask, int N)
|
||||
{
|
||||
Log newLog;
|
||||
strcpy(newLog.instruction, instruction);
|
||||
newLog.mask = 0;
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
if (mask.value[i])
|
||||
{
|
||||
newLog.mask |= (((unsigned long long)1) << i);
|
||||
stats.utilized_lane++;
|
||||
}
|
||||
}
|
||||
stats.total_lane += N;
|
||||
stats.total_instructions += (N > 0);
|
||||
log.push_back(newLog);
|
||||
}
|
||||
|
||||
void Logger::printStats()
|
||||
{
|
||||
printf("****************** Printing Vector Unit Statistics *******************\n");
|
||||
printf("Vector Width: %d\n", VECTOR_WIDTH);
|
||||
printf("Total Vector Instructions: %lld\n", stats.total_instructions);
|
||||
printf("Vector Utilization: %.1f%%\n", (double)stats.utilized_lane / stats.total_lane * 100);
|
||||
printf("Utilized Vector Lanes: %lld\n", stats.utilized_lane);
|
||||
printf("Total Vector Lanes: %lld\n", stats.total_lane);
|
||||
}
|
||||
|
||||
void Logger::printLog()
|
||||
{
|
||||
printf("***************** Printing Vector Unit Execution Log *****************\n");
|
||||
printf(" Instruction | Vector Lane Occupancy ('*' for active, '_' for inactive)\n");
|
||||
printf("------------- --------------------------------------------------------\n");
|
||||
for (int i = 0; i < log.size(); i++)
|
||||
{
|
||||
printf("%12s | ", log[i].instruction);
|
||||
for (int j = 0; j < VECTOR_WIDTH; j++)
|
||||
{
|
||||
if (log[i].mask & (((unsigned long long)1) << j))
|
||||
{
|
||||
printf("*");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("_");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::refresh()
|
||||
{
|
||||
stats.total_instructions = 0;
|
||||
stats.total_lane = 0;
|
||||
stats.utilized_lane = 0;
|
||||
fflush(stdout);
|
||||
};
|
||||
|
||||
unsigned long long Logger::getTotalInstrs()
|
||||
{
|
||||
return stats.total_instructions;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef LOGGER_H_
|
||||
#define LOGGER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
using namespace std;
|
||||
|
||||
#define MAX_INST_LEN 32
|
||||
|
||||
struct __pp_mask;
|
||||
|
||||
struct Log {
|
||||
char instruction[MAX_INST_LEN];
|
||||
unsigned long long mask; // support vector width up to 64
|
||||
};
|
||||
|
||||
struct Statistics {
|
||||
unsigned long long utilized_lane;
|
||||
unsigned long long total_lane;
|
||||
unsigned long long total_instructions;
|
||||
};
|
||||
|
||||
class Logger {
|
||||
private:
|
||||
vector<Log> log;
|
||||
Statistics stats;
|
||||
|
||||
public:
|
||||
void addLog(const char * instruction, __pp_mask mask, int N = 0);
|
||||
void printStats();
|
||||
void printLog();
|
||||
void refresh();
|
||||
unsigned long long getTotalInstrs();
|
||||
};
|
||||
|
||||
#endif
|
||||
Binary file not shown.
+204
@@ -0,0 +1,204 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <math.h>
|
||||
#include "logger.h"
|
||||
#include <sstream>
|
||||
#include "def.h"
|
||||
using namespace std;
|
||||
|
||||
Logger PPLogger;
|
||||
|
||||
void usage(const char *progname);
|
||||
void initValue(float *values, int *exponents, float *output, float *gold, unsigned int N);
|
||||
void absSerial(float *values, float *output, int N);
|
||||
void absVector(float *values, float *output, int N);
|
||||
void clampedExpSerial(float *values, int *exponents, float *output, int N);
|
||||
void clampedExpVector(float *values, int *exponents, float *output, int N);
|
||||
float arraySumSerial(float *values, int N);
|
||||
float arraySumVector(float *values, int N);
|
||||
bool verifyResult(float *values, int *exponents, float *output, float *gold, int N);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int N = 16;
|
||||
bool printLog = false;
|
||||
|
||||
// parse commandline options ////////////////////////////////////////////
|
||||
int opt;
|
||||
static struct option long_options[] = {
|
||||
{"size", 1, 0, 's'},
|
||||
{"log", 0, 0, 'l'},
|
||||
{"help", 0, 0, '?'},
|
||||
{0, 0, 0, 0}};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "s:l?", long_options, NULL)) != EOF)
|
||||
{
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case 's':
|
||||
N = atoi(optarg);
|
||||
if (N <= 0)
|
||||
{
|
||||
printf("Error: Workload size is set to %d (<0).\n", N);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
printLog = true;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
float *values = new float[N + VECTOR_WIDTH];
|
||||
int *exponents = new int[N + VECTOR_WIDTH];
|
||||
float *output = new float[N + VECTOR_WIDTH];
|
||||
float *gold = new float[N + VECTOR_WIDTH];
|
||||
initValue(values, exponents, output, gold, N);
|
||||
|
||||
clampedExpSerial(values, exponents, gold, N);
|
||||
clampedExpVector(values, exponents, output, N);
|
||||
|
||||
//absSerial(values, gold, N);
|
||||
//absVector(values, output, N);
|
||||
|
||||
printf("\e[1;31mCLAMPED EXPONENT\e[0m (required) \n");
|
||||
bool clampedCorrect = verifyResult(values, exponents, output, gold, N);
|
||||
if (printLog)
|
||||
PPLogger.printLog();
|
||||
PPLogger.printStats();
|
||||
|
||||
printf("************************ Result Verification *************************\n");
|
||||
if (!clampedCorrect)
|
||||
{
|
||||
printf("@@@ ClampedExp Failed!!!\n");
|
||||
}
|
||||
else if (PPLogger.getTotalInstrs() == 0)
|
||||
{
|
||||
printf("Not using fake intrinsics in ClampedExp\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ClampedExp Passed!!!\n");
|
||||
}
|
||||
|
||||
PPLogger.refresh();
|
||||
|
||||
printf("\n\e[1;31mARRAY SUM\e[0m (bonus) \n");
|
||||
if (N % VECTOR_WIDTH == 0)
|
||||
{
|
||||
float sumGold = arraySumSerial(values, N);
|
||||
float sumOutput = arraySumVector(values, N);
|
||||
|
||||
if (printLog)
|
||||
PPLogger.printLog();
|
||||
PPLogger.printStats();
|
||||
|
||||
printf("************************ Result Verification *************************\n");
|
||||
|
||||
float epsilon = 0.1;
|
||||
bool sumCorrect = abs(sumGold - sumOutput) < epsilon * 2;
|
||||
if (!sumCorrect)
|
||||
{
|
||||
printf("Expected %f, got %f\n.", sumGold, sumOutput);
|
||||
printf("@@@ ArraySum Failed!!!\n");
|
||||
}
|
||||
else if (PPLogger.getTotalInstrs() == 0)
|
||||
{
|
||||
printf("Not using fake intrinsics in ArraySum\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ArraySum Passed!!!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Must have N %% VECTOR_WIDTH == 0 for this problem (VECTOR_WIDTH is %d)\n", VECTOR_WIDTH);
|
||||
}
|
||||
|
||||
delete[] values;
|
||||
delete[] exponents;
|
||||
delete[] output;
|
||||
delete[] gold;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage(const char *progname)
|
||||
{
|
||||
printf("Usage: %s [options]\n", progname);
|
||||
printf("Program Options:\n");
|
||||
printf(" -s --size <N> Use workload size N (Default = 16)\n");
|
||||
printf(" -l --log Print vector unit execution log\n");
|
||||
printf(" -? --help This message\n");
|
||||
}
|
||||
|
||||
void initValue(float *values, int *exponents, float *output, float *gold, unsigned int N)
|
||||
{
|
||||
|
||||
for (unsigned int i = 0; i < N + VECTOR_WIDTH; i++)
|
||||
{
|
||||
// random input values
|
||||
values[i] = -1.f + 4.f * static_cast<float>(rand()) / RAND_MAX;
|
||||
exponents[i] = rand() % EXP_MAX;
|
||||
output[i] = 0.f;
|
||||
gold[i] = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
bool verifyResult(float *values, int *exponents, float *output, float *gold, int N)
|
||||
{
|
||||
int incorrect = -1;
|
||||
float epsilon = 0.00001;
|
||||
for (int i = 0; i < N + VECTOR_WIDTH; i++)
|
||||
{
|
||||
if (abs(output[i] - gold[i]) > epsilon)
|
||||
{
|
||||
incorrect = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (incorrect != -1)
|
||||
{
|
||||
if (incorrect >= N)
|
||||
printf("You have written to out of bound value!\n");
|
||||
printf("Wrong calculation at value[%d]!\n", incorrect);
|
||||
printf("value = ");
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
printf("% f ", values[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("exp = ");
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
printf("% 9d ", exponents[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("output = ");
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
printf("% f ", output[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("gold = ");
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
printf("% f ", gold[i]);
|
||||
}
|
||||
printf("\n");
|
||||
return false;
|
||||
}
|
||||
printf("Results matched with answer!\n");
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// computes the absolute value of all elements in the input array
|
||||
// values, stores result in output
|
||||
void absSerial(float *values, float *output, int N)
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
float x = values[i];
|
||||
if (x < 0)
|
||||
{
|
||||
output[i] = -x;
|
||||
}
|
||||
else
|
||||
{
|
||||
output[i] = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// accepts an array of values and an array of exponents
|
||||
//
|
||||
// For each element, compute values[i]^exponents[i] and clamp value to
|
||||
// 9.999. Store result in output.
|
||||
void clampedExpSerial(float *values, int *exponents, float *output, int N)
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
float x = values[i];
|
||||
int y = exponents[i];
|
||||
if (y == 0)
|
||||
{
|
||||
output[i] = 1.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float result = x;
|
||||
int count = y - 1;
|
||||
while (count > 0)
|
||||
{
|
||||
result *= x;
|
||||
count--;
|
||||
}
|
||||
if (result > 9.999999f)
|
||||
{
|
||||
result = 9.999999f;
|
||||
}
|
||||
output[i] = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns the sum of all elements in values
|
||||
float arraySumSerial(float *values, int N)
|
||||
{
|
||||
float sum = 0;
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
sum += values[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "PPintrin.h"
|
||||
|
||||
// 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
|
||||
//
|
||||
for (int i = 0; i < N; i += VECTOR_WIDTH)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
//
|
||||
|
||||
for (int i = 0; i < N; i += VECTOR_WIDTH)
|
||||
{
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
Reference in new issue
Block a user