init: HW1

This commit is contained in:
ytshih committed 2026-10-05 04:41:24 +08:00
commit bf65e37202
20 files changed
+1197

No files matched your search

+20
View File
@@ -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 *~
+304
View File
@@ -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);
}
+123
View File
@@ -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
BIN
View File
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
// Define vector unit width here
#ifndef VECTOR_WIDTH
#define VECTOR_WIDTH 4
#endif
#define EXP_MAX 10
+66
View File
@@ -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;
}
+37
View File
@@ -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
BIN
View File
Binary file not shown.
+204
View File
@@ -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;
}
Executable
BIN
View File
Binary file not shown.
+61
View File
@@ -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;
}
+72
View File
@@ -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;
}