From a6479e729fae3be252c119fccf3abcd9907716b9 Mon Sep 17 00:00:00 2001 From: Yi-Ting Shih Date: Mon, 5 Oct 2026 04:41:24 +0800 Subject: [PATCH] init: HW1 --- part1/Makefile | 20 +++ part1/PPintrin.cpp | 304 ++++++++++++++++++++++++++++++++++++++++++++ part1/PPintrin.h | 123 ++++++++++++++++++ part1/PPintrin.o | Bin 0 -> 29896 bytes part1/def.h | 5 + part1/logger.cpp | 66 ++++++++++ part1/logger.h | 37 ++++++ part1/logger.o | Bin 0 -> 5608 bytes part1/main.cpp | 204 +++++++++++++++++++++++++++++ part1/serialOP.cpp | 61 +++++++++ part1/vectorOP.cpp | 72 +++++++++++ part2/Makefile | 53 ++++++++ part2/fasttime.h | 97 ++++++++++++++ part2/main.c | 91 +++++++++++++ part2/test.h | 7 + part2/test1.c | 11 ++ part2/test2.c | 19 +++ part2/test2.c.patch | 13 ++ part2/test3.c | 14 ++ 19 files changed, 1197 insertions(+) create mode 100644 part1/Makefile create mode 100644 part1/PPintrin.cpp create mode 100644 part1/PPintrin.h create mode 100644 part1/PPintrin.o create mode 100644 part1/def.h create mode 100644 part1/logger.cpp create mode 100644 part1/logger.h create mode 100644 part1/logger.o create mode 100644 part1/main.cpp create mode 100644 part1/serialOP.cpp create mode 100644 part1/vectorOP.cpp create mode 100644 part2/Makefile create mode 100644 part2/fasttime.h create mode 100644 part2/main.c create mode 100644 part2/test.h create mode 100644 part2/test1.c create mode 100644 part2/test2.c create mode 100644 part2/test2.c.patch create mode 100644 part2/test3.c diff --git a/part1/Makefile b/part1/Makefile new file mode 100644 index 0000000..46298fa --- /dev/null +++ b/part1/Makefile @@ -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 *~ diff --git a/part1/PPintrin.cpp b/part1/PPintrin.cpp new file mode 100644 index 0000000..311a8ee --- /dev/null +++ b/part1/PPintrin.cpp @@ -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 +void _pp_vset(__pp_vec &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(__pp_vec_float &vecResult, float value, __pp_mask &mask); +template void _pp_vset(__pp_vec_int &vecResult, int value, __pp_mask &mask); + +void _pp_vset_float(__pp_vec_float &vecResult, float value, __pp_mask &mask) { _pp_vset(vecResult, value, mask); } +void _pp_vset_int(__pp_vec_int &vecResult, int value, __pp_mask &mask) { _pp_vset(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 +void _pp_vmove(__pp_vec &dest, __pp_vec &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(__pp_vec_float &dest, __pp_vec_float &src, __pp_mask &mask); +template void _pp_vmove(__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(dest, src, mask); } +void _pp_vmove_int(__pp_vec_int &dest, __pp_vec_int &src, __pp_mask &mask) { _pp_vmove(dest, src, mask); } + +template +void _pp_vload(__pp_vec &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(__pp_vec_float &dest, float *src, __pp_mask &mask); +template void _pp_vload(__pp_vec_int &dest, int *src, __pp_mask &mask); + +void _pp_vload_float(__pp_vec_float &dest, float *src, __pp_mask &mask) { _pp_vload(dest, src, mask); } +void _pp_vload_int(__pp_vec_int &dest, int *src, __pp_mask &mask) { _pp_vload(dest, src, mask); } + +template +void _pp_vstore(T *dest, __pp_vec &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 *dest, __pp_vec_float &src, __pp_mask &mask); +template void _pp_vstore(int *dest, __pp_vec_int &src, __pp_mask &mask); + +void _pp_vstore_float(float *dest, __pp_vec_float &src, __pp_mask &mask) { _pp_vstore(dest, src, mask); } +void _pp_vstore_int(int *dest, __pp_vec_int &src, __pp_mask &mask) { _pp_vstore(dest, src, mask); } + +template +void _pp_vadd(__pp_vec &vecResult, __pp_vec &veca, __pp_vec &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(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask); +template void _pp_vadd(__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(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(vecResult, veca, vecb, mask); } + +template +void _pp_vsub(__pp_vec &vecResult, __pp_vec &veca, __pp_vec &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(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask); +template void _pp_vsub(__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(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(vecResult, veca, vecb, mask); } + +template +void _pp_vmult(__pp_vec &vecResult, __pp_vec &veca, __pp_vec &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(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask); +template void _pp_vmult(__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(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(vecResult, veca, vecb, mask); } + +template +void _pp_vdiv(__pp_vec &vecResult, __pp_vec &veca, __pp_vec &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(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask); +template void _pp_vdiv(__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(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(vecResult, veca, vecb, mask); } + +template +void _pp_vabs(__pp_vec &vecResult, __pp_vec &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(__pp_vec_float &vecResult, __pp_vec_float &veca, __pp_mask &mask); +template void _pp_vabs(__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(vecResult, veca, mask); } +void _pp_vabs_int(__pp_vec_int &vecResult, __pp_vec_int &veca, __pp_mask &mask) { _pp_vabs(vecResult, veca, mask); } + +template +void _pp_vgt(__pp_mask &maskResult, __pp_vec &veca, __pp_vec &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(__pp_mask &maskResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask); +template void _pp_vgt(__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(maskResult, veca, vecb, mask); } +void _pp_vgt_int(__pp_mask &maskResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_vgt(maskResult, veca, vecb, mask); } + +template +void _pp_vlt(__pp_mask &maskResult, __pp_vec &veca, __pp_vec &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(__pp_mask &maskResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask); +template void _pp_vlt(__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(maskResult, veca, vecb, mask); } +void _pp_vlt_int(__pp_mask &maskResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_vlt(maskResult, veca, vecb, mask); } + +template +void _pp_veq(__pp_mask &maskResult, __pp_vec &veca, __pp_vec &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(__pp_mask &maskResult, __pp_vec_float &veca, __pp_vec_float &vecb, __pp_mask &mask); +template void _pp_veq(__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(maskResult, veca, vecb, mask); } +void _pp_veq_int(__pp_mask &maskResult, __pp_vec_int &veca, __pp_vec_int &vecb, __pp_mask &mask) { _pp_veq(maskResult, veca, vecb, mask); } + +template +void _pp_hadd(__pp_vec &vecResult, __pp_vec &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(__pp_vec_float &vecResult, __pp_vec_float &vec); + +void _pp_hadd_float(__pp_vec_float &vecResult, __pp_vec_float &vec) { _pp_hadd(vecResult, vec); } + +template +void _pp_interleave(__pp_vec &vecResult, __pp_vec 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(__pp_vec_float &vecResult, __pp_vec_float vec); + +void _pp_interleave_float(__pp_vec_float &vecResult, __pp_vec_float vec) { _pp_interleave(vecResult, vec); } + +void addUserLog(const char *logStr) +{ + PPLogger.addLog(logStr, _pp_init_ones(), 0); +} diff --git a/part1/PPintrin.h b/part1/PPintrin.h new file mode 100644 index 0000000..f029a87 --- /dev/null +++ b/part1/PPintrin.h @@ -0,0 +1,123 @@ +#ifndef PPINTRIN_H_ +#define PPINTRIN_H_ + +#include +#include +#include "logger.h" +#include "def.h" +//******************* +//* Type Definition * +//******************* + +extern Logger PPLogger; + +template +struct __pp_vec { + T value[VECTOR_WIDTH]; +}; + +// Declare a mask with __pp_mask +struct __pp_mask : __pp_vec {}; + +// Declare a floating point vector register with __pp_vec_float +#define __pp_vec_float __pp_vec + +// Declare an integer vector register with __pp_vec_int +#define __pp_vec_int __pp_vec + +//*********************** +//* 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 diff --git a/part1/PPintrin.o b/part1/PPintrin.o new file mode 100644 index 0000000000000000000000000000000000000000..33c3ac7076dfa85c95640ac7ab220902b92a83b7 GIT binary patch literal 29896 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 P1_s#p8%Qq*qw5C%Mt(C+ literal 0 HcmV?d00001 diff --git a/part1/def.h b/part1/def.h new file mode 100644 index 0000000..a617554 --- /dev/null +++ b/part1/def.h @@ -0,0 +1,5 @@ +// Define vector unit width here +#ifndef VECTOR_WIDTH +#define VECTOR_WIDTH 4 +#endif +#define EXP_MAX 10 diff --git a/part1/logger.cpp b/part1/logger.cpp new file mode 100644 index 0000000..c74d795 --- /dev/null +++ b/part1/logger.cpp @@ -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; +} diff --git a/part1/logger.h b/part1/logger.h new file mode 100644 index 0000000..2dc2634 --- /dev/null +++ b/part1/logger.h @@ -0,0 +1,37 @@ +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include +#include +#include +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; + 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 diff --git a/part1/logger.o b/part1/logger.o new file mode 100644 index 0000000000000000000000000000000000000000..62a42b9dbea10010c3d0f774cbcf811e15ec3732 GIT binary patch literal 5608 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 literal 0 HcmV?d00001 diff --git a/part1/main.cpp b/part1/main.cpp new file mode 100644 index 0000000..e1c5ac3 --- /dev/null +++ b/part1/main.cpp @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include "logger.h" +#include +#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 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(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; +} diff --git a/part1/serialOP.cpp b/part1/serialOP.cpp new file mode 100644 index 0000000..363fa8e --- /dev/null +++ b/part1/serialOP.cpp @@ -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; +} \ No newline at end of file diff --git a/part1/vectorOP.cpp b/part1/vectorOP.cpp new file mode 100644 index 0000000..e3f943a --- /dev/null +++ b/part1/vectorOP.cpp @@ -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; +} \ No newline at end of file diff --git a/part2/Makefile b/part2/Makefile new file mode 100644 index 0000000..7b4a698 --- /dev/null +++ b/part2/Makefile @@ -0,0 +1,53 @@ +TARGET := test_auto_vectorize + +OBJS := main.o test1.o test2.o test3.o + +CC := clang + +CFLAGS := -O3 -std=c11 -Wall -D_POSIX_C_SOURCE=200809L + +ifeq ($(ASSEMBLE),1) + CFLAGS += -S +endif +ifeq ($(VECTORIZE),1) + CFLAGS += -Rpass=loop-vectorize -Rpass-missed=loop-vectorize -Rpass-analysis=loop-vectorize + SUFFIX := .vec +else + CFLAGS += -fno-vectorize + SUFFIX := .novec +endif +ifeq ($(RESTRICT),1) + SUFFIX := $(SUFFIX).restr +endif +ifeq ($(ALIGN),1) + SUFFIX := $(SUFFIX).align +endif +ifeq ($(AVX2),1) + CFLAGS += -mavx2 + SUFFIX := $(SUFFIX).avx2 +endif +ifeq ($(FASTMATH),1) + CFLAGS += -ffast-math + SUFFIX := $(SUFFIX).fmath +endif + +all: $(TARGET) + +%.o: %.c test.h +ifeq ($(ASSEMBLE),1) + mkdir -p "./assembly" + $(CC) $(CFLAGS) -c $< -o assembly/$(basename $<)$(SUFFIX).s +else + $(CC) $(CFLAGS) -c $< +endif + +$(TARGET): $(OBJS) +ifneq ($(ASSEMBLE),1) + $(CC) $(CFLAGS) $(OBJS) -o $@ +endif + +clean: + $(RM) *.o *.s $(TARGET) *~ + +cleanall: + $(RM) -r *.o *.s $(TARGET) *~ assembly diff --git a/part2/fasttime.h b/part2/fasttime.h new file mode 100644 index 0000000..f12c856 --- /dev/null +++ b/part2/fasttime.h @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2014 MIT License by 6.172 Staff + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + **/ + +#ifndef INCLUDED_FASTTIME_DOT_H +#define INCLUDED_FASTTIME_DOT_H + +#define _POSIX_C_SOURCE 200809L + +#include + +#ifdef __MACH__ +#include // mach_absolute_time + +typedef uint64_t fasttime_t; + + +// Return the current time. +static inline fasttime_t gettime(void) { + return mach_absolute_time(); +} + +// Return the time different between the start and the end, as a float +// in units of seconds. This function does not need to be fast. +// Implementation notes: See +// https://developer.apple.com/library/mac/qa/qa1398/_index.html +static inline double tdiff(fasttime_t start, fasttime_t end) { + static mach_timebase_info_data_t timebase; + int r = mach_timebase_info(&timebase); + assert(r == 0); + fasttime_t elapsed = end-start; + double ns = (double)elapsed * timebase.numer / timebase.denom; + return ns*1e-9; +} + +static inline unsigned int random_seed_from_clock(void) { + fasttime_t now = gettime(); + return (now & 0xFFFFFFFF) + (now>>32); +} + +#else // LINUX + +// We need _POSIX_C_SOURCE to pick up 'struct timespec' and clock_gettime. +// #define _POSIX_C_SOURCE 200809L + +#include + +typedef struct timespec fasttime_t; + +// Return the current time. +static inline fasttime_t gettime(void) { + struct timespec s; +#ifdef NDEBUG + clock_gettime(CLOCK_MONOTONIC, &s); +#else + int r = clock_gettime(CLOCK_MONOTONIC, &s); + assert(r == 0); +#endif + return s; +} + +// Return the time different between the start and the end, as a float +// in units of seconds. This function does not need to be fast. +static inline double tdiff(fasttime_t start, fasttime_t end) { + return end.tv_sec - start.tv_sec + 1e-9*(end.tv_nsec - start.tv_nsec); +} + +static inline unsigned int random_seed_from_clock(void) { + fasttime_t now = gettime(); + return now.tv_sec + now.tv_nsec; +} + +// Poison these symbols to help find portability problems. +int clock_gettime(clockid_t, struct timespec *) __attribute__((deprecated)); +time_t time(time_t *) __attribute__((deprecated)); + +#endif // LINUX + +#endif // INCLUDED_FASTTIME_DOT_H diff --git a/part2/main.c b/part2/main.c new file mode 100644 index 0000000..939b186 --- /dev/null +++ b/part2/main.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include "fasttime.h" +#include "test.h" + +void usage(const char *progname); +void initValue(float *values1, float *values2, double *value3, float *output, unsigned int N); + +extern void test1(float *a, float *b, float *c, int N); +extern void test2(float *__restrict a, float *__restrict b, float *__restrict c, int N); +extern double test3(double *__restrict a, int N) ; + +int main(int argc, char **argv) { + int N = 1024; + int whichTestToRun = 1; + + // parse commandline options + int opt; + static struct option long_options[] = { + {"size", 1, 0, 's'}, + {"test", 1, 0, 't'}, + {"help", 0, 0, '?'}, + {0 ,0, 0, 0} + }; + + while ((opt = getopt_long(argc, argv, "st:?", 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 't': + whichTestToRun = atoi(optarg); + if (whichTestToRun <= 0 || whichTestToRun >= 4) { + printf("Error: test%d() is not available.\n", whichTestToRun); + return -1; + } + break; + case 'h': + default: + usage(argv[0]); + return 1; + } + } + +#define AVX_ALIGNMENT 256 + float *values1 = (float *)__builtin_alloca_with_align(N * sizeof(float), AVX_ALIGNMENT); + float *values2 = (float *)__builtin_alloca_with_align(N * sizeof(float), AVX_ALIGNMENT); + double *values3 = (double *)__builtin_alloca_with_align(N * sizeof(double), AVX_ALIGNMENT); + float *output = (float *)__builtin_alloca_with_align(N * sizeof(float), AVX_ALIGNMENT); +#undef AVX_ALIGNMENT + initValue(values1, values2, values3, output, N); + + printf("Running test%d()...\n", whichTestToRun); + fasttime_t time1 = gettime(); + switch (whichTestToRun) { + case 1: test1(values1, values2, output, N); break; + case 2: test2(values1, values2, output, N); break; + case 3: test3(values3, N); break; + } + fasttime_t time2 = gettime(); + + double elapsedf = tdiff(time1, time2); + printf("Elapsed execution time of the loop in test%d():\n", whichTestToRun); + printf("%lfsec (N: %d, I: %d)\n", elapsedf, N, I); + return 0; +} + +void usage(const char *progname) { + printf("Usage: %s [options]\n", progname); + printf("Program Options:\n"); + printf(" -s --size Use workload size N (Default = 1024)\n"); + printf(" -t --test Just run the testN function (Default = 1)\n"); + printf(" -h --help This message\n"); +} + +void initValue(float *values1, float *values2, double *values3, float *output, unsigned int N) { + for (unsigned int i=0; i a[j]) + c[j] = b[j]; + } + } +} diff --git a/part2/test2.c.patch b/part2/test2.c.patch new file mode 100644 index 0000000..67b5857 --- /dev/null +++ b/part2/test2.c.patch @@ -0,0 +1,13 @@ +--- test2.c ++++ test2.c +@@ -14,9 +14,8 @@ + for (int j = 0; j < N; j++) + { + /* max() */ +- c[j] = a[j]; +- if (b[j] > a[j]) +- c[j] = b[j]; ++ if (b[j] > a[j]) c[j] = b[j]; ++ else c[j] = a[j]; + } + } diff --git a/part2/test3.c b/part2/test3.c new file mode 100644 index 0000000..05a3468 --- /dev/null +++ b/part2/test3.c @@ -0,0 +1,14 @@ +#include "test.h" + +double test3(double *__restrict a, int N) { + __builtin_assume(N == 1024); + a = (double *)__builtin_assume_aligned(a, 16); + + double b = 0; + for (int i=0; i