From 5dcef2cefce09bc7dc6f9cd61b547ad5105eeab4 Mon Sep 17 00:00:00 2001
From: Maria Kotsifakou <kotsifa2@illinois.edu>
Date: Fri, 1 Nov 2019 19:04:06 -0500
Subject: [PATCH] Wrapper API and placeholder runtime functions for image
 processing

---
 .../include/approxhpvm_img_runtime_utils.h    | 238 ++++++++++++++++++
 .../include/img_tensor_runtime.h              |  26 ++
 .../tensor_runtime/include/tensor_runtime.h   |   1 +
 .../tensor_runtime/src/img_tensor_runtime.cu  | 137 ++++++++++
 4 files changed, 402 insertions(+)
 create mode 100644 llvm/projects/hpvm-tensor-rt/tensor_runtime/include/approxhpvm_img_runtime_utils.h
 create mode 100644 llvm/projects/hpvm-tensor-rt/tensor_runtime/include/img_tensor_runtime.h
 create mode 100644 llvm/projects/hpvm-tensor-rt/tensor_runtime/src/img_tensor_runtime.cu

diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/approxhpvm_img_runtime_utils.h b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/approxhpvm_img_runtime_utils.h
new file mode 100644
index 0000000000..dc5cddf8a2
--- /dev/null
+++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/approxhpvm_img_runtime_utils.h
@@ -0,0 +1,238 @@
+#ifndef APPROXHPVM_IMG_RUNTIME_UTILS
+#define APPROXHPVM_IMG_RUNTIME_UTILS
+
+#include "configuration.h"
+#include "hpvm-rt-controller.h"
+
+#include "img_tensor_runtime.h"
+
+
+// Utilities header for ApproxHPVM image runtime API (wrapper runtime API)
+
+void* handleTensorFftApproximationTuples(
+  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
+   void* input) {
+
+  if (approxTuples.size() == 1) {
+    enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
+    int param = approxTuples[0].second;
+    switch (approx) {
+      case GPUNodeConfiguration::APPROX::FP32 :
+        {
+        void* t_out;
+        RC->resume_profiler();
+        t_out = tensorFft(input); //TODO: correct name here
+        RC->pause_profiler();
+        std::pair<double, double> pinfo = RC->get_time_energy();
+        RC->reset_profiler();
+        RC->addToCurrentIterationComputeTime("tensorFft", pinfo.first); // and here
+        RC->addToCurrentIterationComputeEnergy("tensorFft", pinfo.second); // and here
+        return t_out;
+        }
+      default :
+        CUSTOM_ASSERT(false && "Unknown approximation type");
+        ERROR("Unknown approximation type");
+        abort();
+      // TODO additional approx methods implemented here
+      }
+    } else if (approxTuples.size() == 2) {
+      ERROR("Currently unsupported case");
+      abort();
+    } else {
+      ERROR("Unsupported case");
+      abort();
+    }
+  return NULL;
+}
+
+void* handleTensorReduceApproximationTuples(
+  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
+   void* input) {
+  if (approxTuples.size() == 1) {
+    enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
+    int param = approxTuples[0].second;
+    switch (approx) {
+      case GPUNodeConfiguration::APPROX::FP32 :
+        {
+        void* t_out;
+        RC->resume_profiler();
+        t_out = tensorReduce(input); //TODO: correct name here
+        RC->pause_profiler();
+        std::pair<double, double> pinfo = RC->get_time_energy();
+        RC->reset_profiler();
+        RC->addToCurrentIterationComputeTime("tensorReduce", pinfo.first); // and here
+        RC->addToCurrentIterationComputeEnergy("tensorReduce", pinfo.second); // and here
+        return t_out;
+        }
+      case GPUNodeConfiguration::APPROX::REDUCTION_SAMPLING :
+        {
+        void* t_out;
+        RC->resume_profiler();
+        t_out = tensorReductionSamplingReduce(input); //TODO: correct name here
+        RC->pause_profiler();
+        std::pair<double, double> pinfo = RC->get_time_energy();
+        RC->reset_profiler();
+        RC->addToCurrentIterationComputeTime("tensorReductionSamplingReduce",
+                                              pinfo.first); // and here
+        RC->addToCurrentIterationComputeEnergy("tensorReductionSamplingReduce",
+                                                pinfo.second); // and here
+        return t_out;
+        }
+      default :
+        CUSTOM_ASSERT(false && "Unknown approximation type");
+        ERROR("Unknown approximation type");
+        abort();
+      // TODO additional approx methods implemented here
+      }
+    } else if (approxTuples.size() == 2) {
+      ERROR("Currently unsupported case");
+      abort();
+    } else {
+      ERROR("Unsupported case");
+      abort();
+    }
+  return NULL;
+}
+
+void* handleTensorProjectiveTApproximationTuples(
+  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
+   void* input) {
+  if (approxTuples.size() == 1) {
+    enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
+    int param = approxTuples[0].second;
+    switch (approx) {
+      case GPUNodeConfiguration::APPROX::FP32 :
+        {
+        void* t_out;
+        RC->resume_profiler();
+        t_out = tensorProjectiveT(input); //TODO: correct name here
+        RC->pause_profiler();
+        std::pair<double, double> pinfo = RC->get_time_energy();
+        RC->reset_profiler();
+        RC->addToCurrentIterationComputeTime("tensorProjectiveT", pinfo.first); // and here
+        RC->addToCurrentIterationComputeEnergy("tensorProjectiveT", pinfo.second); // and here
+        return t_out;
+        }
+      default :
+        CUSTOM_ASSERT(false && "Unknown approximation type");
+        ERROR("Unknown approximation type");
+        abort();
+      // TODO additional approx methods implemented here
+      }
+    } else if (approxTuples.size() == 2) {
+      ERROR("Currently unsupported case");
+      abort();
+    } else {
+      ERROR("Unsupported case");
+      abort();
+    }
+  return NULL;
+}
+
+void* handleTensorMap1ApproximationTuples(
+  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
+   void* input) {
+  if (approxTuples.size() == 1) {
+    enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
+    int param = approxTuples[0].second;
+    switch (approx) {
+      case GPUNodeConfiguration::APPROX::FP32 :
+        {
+        void* t_out;
+        RC->resume_profiler();
+        t_out = tensorMap1(input); //TODO: correct name here
+        RC->pause_profiler();
+        std::pair<double, double> pinfo = RC->get_time_energy();
+        RC->reset_profiler();
+        RC->addToCurrentIterationComputeTime("tensorMap1", pinfo.first); // and here
+        RC->addToCurrentIterationComputeEnergy("tensorMap1", pinfo.second); // and here
+        return t_out;
+        }
+      default :
+        CUSTOM_ASSERT(false && "Unknown approximation type");
+        ERROR("Unknown approximation type");
+        abort();
+      // TODO additional approx methods implemented here
+      }
+    } else if (approxTuples.size() == 2) {
+      ERROR("Currently unsupported case");
+      abort();
+    } else {
+      ERROR("Unsupported case");
+      abort();
+    }
+  return NULL;
+}
+
+void* handleTensorMap2ApproximationTuples(
+  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
+   void* input) {
+  if (approxTuples.size() == 1) {
+    enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
+    int param = approxTuples[0].second;
+    switch (approx) {
+      case GPUNodeConfiguration::APPROX::FP32 :
+        {
+        void* t_out;
+        RC->resume_profiler();
+        t_out = tensorMap2(input); //TODO: correct name here
+        RC->pause_profiler();
+        std::pair<double, double> pinfo = RC->get_time_energy();
+        RC->reset_profiler();
+        RC->addToCurrentIterationComputeTime("tensorMap2", pinfo.first); // and here
+        RC->addToCurrentIterationComputeEnergy("tensorMap2", pinfo.second); // and here
+        return t_out;
+        }
+      default :
+        CUSTOM_ASSERT(false && "Unknown approximation type");
+        ERROR("Unknown approximation type");
+        abort();
+      // TODO additional approx methods implemented here
+      }
+    } else if (approxTuples.size() == 2) {
+      ERROR("Currently unsupported case");
+      abort();
+    } else {
+      ERROR("Unsupported case");
+      abort();
+    }
+  return NULL;
+}
+
+void* handleTensorMap3ApproximationTuples(
+  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
+   void* input) {
+  if (approxTuples.size() == 1) {
+    enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
+    int param = approxTuples[0].second;
+    switch (approx) {
+      case GPUNodeConfiguration::APPROX::FP32 :
+        {
+        void* t_out;
+        RC->resume_profiler();
+        t_out = tensorMap3(input); //TODO: correct name here
+        RC->pause_profiler();
+        std::pair<double, double> pinfo = RC->get_time_energy();
+        RC->reset_profiler();
+        RC->addToCurrentIterationComputeTime("tensorMap3", pinfo.first); // and here
+        RC->addToCurrentIterationComputeEnergy("tensorMap3", pinfo.second); // and here
+        return t_out;
+        }
+      default :
+        CUSTOM_ASSERT(false && "Unknown approximation type");
+        ERROR("Unknown approximation type");
+        abort();
+      // TODO additional approx methods implemented here
+      }
+    } else if (approxTuples.size() == 2) {
+      ERROR("Currently unsupported case");
+      abort();
+    } else {
+      ERROR("Unsupported case");
+      abort();
+    }
+  return NULL;
+}
+
+
+#endif
diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/img_tensor_runtime.h b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/img_tensor_runtime.h
new file mode 100644
index 0000000000..9c098719e5
--- /dev/null
+++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/img_tensor_runtime.h
@@ -0,0 +1,26 @@
+#ifndef IMG_TENSOR_RUNTIME_H
+#define IMG_TENSOR_RUNTIME_H
+
+// ***                        Runtime declaration                        *** //
+void* tensorFft(void* input);
+void* tensorReduce(void* input);
+void* tensorReductionSamplingReduce(void* input);
+void* tensorProjectiveT(void* input);
+void* tensorMap1(void* input);
+void* tensorMap2(void* input);
+void* tensorMap3(void* input);
+
+// ***                      Wrapper API declaration                      *** //
+void* wrapper_tensorFft(const char* hpvm_node_id, void* input);
+void* wrapper_tensorReduce(const char* hpvm_node_id, void* input);
+void* wrapper_tensorProjectiveT(const char* hpvm_node_id, void* input);
+void* wrapper_tensorMap1(const char* hpvm_node_id, void* input);
+void* wrapper_tensorMap2(const char* hpvm_node_id, void* input);
+void* wrapper_tensorMap3(const char* hpvm_node_id, void* input);
+
+// Tentative
+void* wrapper_tensorStencil(const char* hpvm_node_id, void* input);
+void* wrapper_tensorCosineT(const char* hpvm_node_id, void* input);
+
+
+#endif
diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/tensor_runtime.h b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/tensor_runtime.h
index 6041bb4de9..06c492c9e8 100644
--- a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/tensor_runtime.h
+++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/tensor_runtime.h
@@ -10,6 +10,7 @@
 #include "tensor.h"
 #include "rt-controller-api.h"
 
+#include "img_tensor_runtime.h"
 
 #ifndef CUDNN_HEADER
 #define CUDNN_HEADER
diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/img_tensor_runtime.cu b/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/img_tensor_runtime.cu
new file mode 100644
index 0000000000..0460e490fd
--- /dev/null
+++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/img_tensor_runtime.cu
@@ -0,0 +1,137 @@
+#include "../include/debug.h"
+#include "../include/img_tensor_runtime.h"
+#include "../include/approxhpvm_img_runtime_utils.h" 
+
+// ***                       Runtime implementation                      *** //
+void* tensorFft(void* input) {
+
+}
+
+void* tensorReduce(void* input) {
+
+}
+
+void* tensorReductionSamplingReduce(void* input) {
+
+}
+
+void* tensorProjectiveT(void* input) {
+
+}
+
+void* tensorMap1(void* input) {
+
+}
+
+void* tensorMap2(void* input) {
+
+}
+
+void* tensorMap3(void* input) {
+
+}
+
+
+// ***                     Wrapper API implementation                    *** //
+
+void* wrapper_tensorFft(const char* hpvm_node_id, void* input) {
+  GPUNodeConfiguration *GPUConf =
+    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
+                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
+                                                 int> > > > &ApproxChoices =
+    GPUConf->getApproxChoices();
+  // Approximation choices must be for a fft operation
+  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
+         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::FFT &&
+         "Invalid configuration generated for tensor fft wrapper operation");
+  return handleTensorFftApproximationTuples(ApproxChoices[0].second,
+                                            input);
+}
+
+void* wrapper_tensorReduce(const char* hpvm_node_id, void* input) {
+  GPUNodeConfiguration *GPUConf =
+    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
+                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
+                                                 int> > > > &ApproxChoices =
+    GPUConf->getApproxChoices();
+  // Approximation choices must be for a reduce operation
+  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
+         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::REDUCE &&
+         "Invalid configuration generated for tensor reduce wrapper operation");
+  return handleTensorReduceApproximationTuples(ApproxChoices[0].second,
+                                            input);
+}
+
+void* wrapper_tensorProjectiveT(const char* hpvm_node_id, void* input) {
+  GPUNodeConfiguration *GPUConf =
+    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
+                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
+                                                 int> > > > &ApproxChoices =
+    GPUConf->getApproxChoices();
+  // Approximation choices must be for a projectiveT operation
+  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
+         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::PROJECTIVE_T &&
+         "Invalid configuration generated for tensor projectiveT wrapper operation");
+  return handleTensorProjectiveTApproximationTuples(ApproxChoices[0].second,
+                                            input);
+}
+
+void* wrapper_tensorMap1(const char* hpvm_node_id, void* input) {
+  GPUNodeConfiguration *GPUConf =
+    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
+                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
+                                                 int> > > > &ApproxChoices =
+    GPUConf->getApproxChoices();
+  // Approximation choices must be for a map1 operation
+  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
+         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::MAP1 &&
+         "Invalid configuration generated for tensor map1 wrapper operation");
+  return handleTensorMap1ApproximationTuples(ApproxChoices[0].second,
+                                            input);
+}
+
+void* wrapper_tensorMap2(const char* hpvm_node_id, void* input) {
+  GPUNodeConfiguration *GPUConf =
+    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
+                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
+                                                 int> > > > &ApproxChoices =
+    GPUConf->getApproxChoices();
+  // Approximation choices must be for a map2 operation
+  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
+         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::MAP2 &&
+         "Invalid configuration generated for tensor map2 wrapper operation");
+  return handleTensorMap2ApproximationTuples(ApproxChoices[0].second,
+                                            input);
+}
+
+void* wrapper_tensorMap3(const char* hpvm_node_id, void* input) {
+  GPUNodeConfiguration *GPUConf =
+    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
+                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
+                                                 int> > > > &ApproxChoices =
+    GPUConf->getApproxChoices();
+  // Approximation choices must be for a map3 operation
+  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
+         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::MAP3 &&
+         "Invalid configuration generated for tensor map3 wrapper operation");
+  return handleTensorMap3ApproximationTuples(ApproxChoices[0].second,
+                                            input);
+}
+
+// Tentative
+void* wrapper_tensorStencil(const char* hpvm_node_id, void* input) {
+  ERROR("Stencil operation currently unsupported.\n");
+  abort();
+}
+
+void* wrapper_tensorCosineT(const char* hpvm_node_id, void* input) {
+  ERROR("CosineT operation currently unsupported.\n");
+  abort();
+}
+
-- 
GitLab