[Beignet] [PATCH 2/6] Add the Serialization and DeSerialization logic to gbe::kernel and gbe::program

junyan.he at inbox.com junyan.he at inbox.com
Thu Aug 22 01:18:37 PDT 2013


From: Junyan He <junyan.he at linux.intel.com>

Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 backend/src/backend/program.cpp |  397 +++++++++++++++++++++++++++++++++++++++
 backend/src/backend/program.hpp |   61 +++++-
 backend/src/ir/constant.hpp     |    6 +
 backend/src/ir/image.hpp        |    3 +
 backend/src/ir/sampler.hpp      |    3 +
 backend/src/sys/platform.hpp    |   22 +++
 6 files changed, 489 insertions(+), 3 deletions(-)

diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index 35d3a7c..dec5ae4 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -37,6 +37,7 @@
 #include <fstream>
 #include <dlfcn.h>
 #include <sstream>
+#include <iostream>
 #include <unistd.h>
 
 /* Not defined for LLVM 3.0 */
@@ -124,6 +125,402 @@ namespace gbe {
     return true;
   }
 
+#define OUT_UPDATE_SZ(elt) \
+  do { \
+      auto tmp_val = elt;\
+      souts.write((char *)(&tmp_val), sizeof(elt));  \
+      ret_size += sizeof(elt); \
+  } while(0)
+
+#define IN_UPDATE_SZ(elt) \
+  do { \
+      ins.read((char *)(&(elt)), sizeof(elt));  \
+      total_size -= sizeof(elt); \
+  } while(0)
+
+  size_t Program::serializeToBin(std::ostream& outs) {
+    size_t ret_size = 0;
+    std::ostringstream souts(std::ostringstream::binary);
+    unsigned int i;
+    size_t const_num = constantSet ? constantSet->getConstantNum() : 0;
+    size_t ker_num = kernels.size();
+    size_t global_data_sz = constantSet ? constantSet->getDataSize() : 0;
+
+    OUT_UPDATE_SZ(magic_begin);
+    OUT_UPDATE_SZ(ker_num);
+    OUT_UPDATE_SZ(const_num);
+    OUT_UPDATE_SZ(global_data_sz);
+
+    if (global_data_sz > 0) {
+      char* mem = reinterpret_cast<char *>(::malloc(sizeof(char)*global_data_sz));
+      if (!mem)
+        return false;
+
+      getGlobalConstantData(mem);
+
+      for (i = 0; i < global_data_sz; i++)
+        OUT_UPDATE_SZ(mem[i]);
+
+      ::free(mem);
+    }
+
+    for (i = 0; i < const_num; i++) {
+      size_t bytes = sizeof(constantSet->getConstant(i).getName().size()) //name length
+          + constantSet->getConstant(i).getName().size()*sizeof(char) //name
+          + sizeof(constantSet->getConstant(i).getSize())  //size
+          + sizeof(constantSet->getConstant(i).getAlignment())  //alignment
+          + sizeof(constantSet->getConstant(i).getOffset())  //offset
+          + sizeof(constantSet->getConstant(i).getReg());  //reg
+      OUT_UPDATE_SZ(bytes);
+
+      OUT_UPDATE_SZ(constantSet->getConstant(i).getName().size());
+      outs.write(constantSet->getConstant(i).getName().c_str(),
+                 constantSet->getConstant(i).getName().size());
+      ret_size += sizeof(char)*constantSet->getConstant(i).getName().size();
+      OUT_UPDATE_SZ(constantSet->getConstant(i).getSize());
+      OUT_UPDATE_SZ(constantSet->getConstant(i).getAlignment());
+      OUT_UPDATE_SZ(constantSet->getConstant(i).getOffset());
+      OUT_UPDATE_SZ(constantSet->getConstant(i).getReg());
+    }
+
+    for (auto ker : kernels) {
+      size_t sz = ker.second->serializeToBin(souts);
+      if (!sz)
+        return 0;
+
+      ret_size += sz;
+    }
+
+    OUT_UPDATE_SZ(magic_end);
+
+    outs.write((char *)&ret_size, sizeof(ret_size));
+    outs.write(souts.str().c_str(), souts.str().size());
+    ret_size += sizeof(ret_size);
+    return ret_size;
+  }
+
+  size_t Program::deserializeFromBin(std::istream& ins) {
+    size_t total_size = 0;
+    size_t ret_size = 0;
+    uint32_t magic;
+    size_t ker_num;
+    size_t const_num;
+    size_t global_data_sz;
+
+    ins.read((char *)&total_size, sizeof(total_size));
+    ret_size = total_size + sizeof(total_size);
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_begin)
+      return 0;
+
+    IN_UPDATE_SZ(ker_num);
+    IN_UPDATE_SZ(const_num);
+    IN_UPDATE_SZ(global_data_sz);
+
+    constantSet = new ir::ConstantSet;
+    if (const_num || global_data_sz) {
+      char tmp;
+      size_t const_bytes;
+      IN_UPDATE_SZ(const_bytes);
+
+      for (unsigned int i = 0; i < global_data_sz; i++) {
+        IN_UPDATE_SZ(tmp);
+        constantSet->data.push_back(tmp);
+      }
+
+      for (unsigned int i = 0; i < const_num; i++) {
+        size_t name_len;
+        IN_UPDATE_SZ(name_len);
+        char* c_name = new char[name_len];
+        ins.read(c_name, name_len);
+        total_size -= sizeof(char)*name_len;
+        uint32_t size, align, offset;
+        uint16_t reg;
+        IN_UPDATE_SZ(size);
+        IN_UPDATE_SZ(align);
+        IN_UPDATE_SZ(offset);
+        IN_UPDATE_SZ(reg);
+        std::string name(c_name);
+        delete[] c_name;
+
+        const ir::Constant constant(name, size, align, offset);
+        constantSet->constants.push_back(constant);
+
+        const_bytes -= sizeof(name_len) + name_len * sizeof(char)
+            + sizeof(size) + sizeof(align) + sizeof(offset) + sizeof(reg);
+
+        if (const_bytes) {
+          return 0;
+        }
+      }
+    }
+
+    for (unsigned int i = 0; i < ker_num; i++) {
+      size_t ker_serial_sz;
+      std::string ker_name; // Just a empty name here.
+      Kernel* ker = allocateKernel(ker_name);
+      if(!(ker_serial_sz = ker->deserializeFromBin(ins)))
+        return 0;
+
+      kernels.insert(std::make_pair(ker->getName(), ker));
+      total_size -= ker_serial_sz;
+    }
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_end)
+      return 0;
+
+    if (total_size)
+      return 0;
+
+    return ret_size;
+  }
+
+  size_t Kernel::serializeToBin(std::ostream& outs) {
+    unsigned int i;
+    size_t ret_size = 0;
+    std::ostringstream souts(std::ostringstream::binary);
+
+    OUT_UPDATE_SZ(magic_begin);
+
+    OUT_UPDATE_SZ(name.size());
+    souts.write(name.c_str(), name.size());
+    ret_size += sizeof(char)*name.size();
+
+    OUT_UPDATE_SZ(argNum);
+    for (i = 0; i < argNum; i++) {
+      KernelArgument& arg = args[i];
+      OUT_UPDATE_SZ(arg.type);
+      OUT_UPDATE_SZ(arg.size);
+      OUT_UPDATE_SZ(arg.bufSize);
+    }
+
+    OUT_UPDATE_SZ(patches.size());
+    for (auto patch : patches) {
+      unsigned int tmp;
+      tmp = patch.type;
+      OUT_UPDATE_SZ(tmp);
+      tmp = patch.subType;
+      OUT_UPDATE_SZ(tmp);
+      tmp = patch.offset;
+      OUT_UPDATE_SZ(tmp);
+    }
+
+    OUT_UPDATE_SZ(curbeSize);
+    OUT_UPDATE_SZ(simdWidth);
+    OUT_UPDATE_SZ(stackSize);
+    OUT_UPDATE_SZ(useSLM);
+
+    /* samplers. */
+    if (samplerSet) {
+      OUT_UPDATE_SZ(samplerSet->samplerMap.size());
+      for (auto iter : samplerSet->samplerMap) {
+        OUT_UPDATE_SZ(iter.first);
+        OUT_UPDATE_SZ(iter.second.reg);
+        OUT_UPDATE_SZ(iter.second.slot);
+      }
+
+      OUT_UPDATE_SZ(samplerSet->regMap.size());
+      for (auto iter : samplerSet->regMap) {
+        OUT_UPDATE_SZ(iter.first);
+        OUT_UPDATE_SZ(iter.second.reg);
+        OUT_UPDATE_SZ(iter.second.slot);
+      }
+    }
+
+    /* images. */
+    if (imageSet) {
+      OUT_UPDATE_SZ(imageSet->regMap.size());
+      for (auto iter : imageSet->regMap) {
+        OUT_UPDATE_SZ(iter.first);
+        OUT_UPDATE_SZ(iter.second->arg_idx);
+        OUT_UPDATE_SZ(iter.second->idx);
+        OUT_UPDATE_SZ(iter.second->wSlot);
+        OUT_UPDATE_SZ(iter.second->hSlot);
+        OUT_UPDATE_SZ(iter.second->depthSlot);
+        OUT_UPDATE_SZ(iter.second->dataTypeSlot);
+        OUT_UPDATE_SZ(iter.second->channelOrderSlot);
+        OUT_UPDATE_SZ(iter.second->dimOrderSlot);
+      }
+
+      OUT_UPDATE_SZ(imageSet->indexMap.size());
+      for (auto iter : imageSet->indexMap) {
+        OUT_UPDATE_SZ(iter.first);
+        OUT_UPDATE_SZ(iter.second->arg_idx);
+        OUT_UPDATE_SZ(iter.second->idx);
+        OUT_UPDATE_SZ(iter.second->wSlot);
+        OUT_UPDATE_SZ(iter.second->hSlot);
+        OUT_UPDATE_SZ(iter.second->depthSlot);
+        OUT_UPDATE_SZ(iter.second->dataTypeSlot);
+        OUT_UPDATE_SZ(iter.second->channelOrderSlot);
+        OUT_UPDATE_SZ(iter.second->dimOrderSlot);
+      }
+    }
+
+    /* Code. */
+    const char * code = getCode();
+    OUT_UPDATE_SZ(getCodeSize());
+    for (i = 0; i < getCodeSize(); i++) {
+      OUT_UPDATE_SZ(code[i]);
+    }
+
+    OUT_UPDATE_SZ(magic_end);
+
+    outs.write((char *)&ret_size, sizeof(ret_size));
+    outs.write(souts.str().c_str(), souts.str().size());
+    ret_size += sizeof(ret_size);
+    return ret_size;
+  }
+
+  size_t Kernel::deserializeFromBin(std::istream& ins) {
+    size_t total_size = 0;
+    size_t ret_size = 0;
+    uint32_t magic = 0;
+    size_t patch_num = 0;
+    size_t image_map_sz = 0;
+    size_t sampler_map_sz = 0;
+    size_t code_size = 0;
+
+    ins.read((char *)&total_size, sizeof(total_size));
+    ret_size = total_size + sizeof(total_size);
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_begin)
+      return 0;
+
+    size_t name_len;
+    IN_UPDATE_SZ(name_len);
+    char* c_name = new char[name_len];
+    ins.read(c_name, name_len);
+    total_size -= sizeof(char)*name_len;
+
+    name = c_name;
+    delete[] c_name;
+
+    IN_UPDATE_SZ(argNum);
+    GBE_NEW_ARRAY_NO_ARG(KernelArgument, argNum);
+
+    args = GBE_NEW_ARRAY_NO_ARG(KernelArgument, argNum);
+    for (uint32_t i = 0; i < argNum; i++) {
+      KernelArgument& arg = args[i];
+      IN_UPDATE_SZ(arg.type);
+      IN_UPDATE_SZ(arg.size);
+      IN_UPDATE_SZ(arg.bufSize);
+    }
+
+    IN_UPDATE_SZ(patch_num);
+    for (uint32_t i = 0; i < patch_num; i++) {
+      unsigned int tmp;
+      PatchInfo patch;
+      IN_UPDATE_SZ(tmp);
+      patch.type = tmp;
+      IN_UPDATE_SZ(tmp);
+      patch.subType = tmp;
+      IN_UPDATE_SZ(tmp);
+      patch.offset = tmp;
+
+      patches.push_back(patch);
+    }
+
+    IN_UPDATE_SZ(curbeSize);
+    IN_UPDATE_SZ(simdWidth);
+    IN_UPDATE_SZ(stackSize);
+    IN_UPDATE_SZ(useSLM);
+
+    samplerSet = GBE_NEW(ir::SamplerSet);
+
+    IN_UPDATE_SZ(sampler_map_sz); //samplerMap
+    if (sampler_map_sz){
+      for (uint32_t i = 0; i < sampler_map_sz; i++) {
+        uint32_t key;
+        ir::SamplerRegSlot reg_slot;
+
+        IN_UPDATE_SZ(key);
+        IN_UPDATE_SZ(reg_slot.reg);
+        IN_UPDATE_SZ(reg_slot.slot);
+        samplerSet->samplerMap.insert(std::make_pair(key, reg_slot));
+      }
+    }
+
+    IN_UPDATE_SZ(sampler_map_sz);  //regMap
+    if (sampler_map_sz){
+      for (uint32_t i = 0; i < sampler_map_sz; i++) {
+        ir::Register key;
+        ir::SamplerRegSlot reg_slot;
+
+        IN_UPDATE_SZ(key);
+        IN_UPDATE_SZ(reg_slot.reg);
+        IN_UPDATE_SZ(reg_slot.slot);
+        samplerSet->regMap.insert(std::make_pair(key, reg_slot));
+      }
+    }
+
+    imageSet = GBE_NEW(ir::ImageSet);
+
+    IN_UPDATE_SZ(image_map_sz); //regMap
+    if (image_map_sz){
+      for (uint32_t i = 0; i < image_map_sz; i++) {
+        ir::Register reg;
+        ImageInfo *img_info = GBE_NEW(struct ImageInfo);;
+
+        IN_UPDATE_SZ(reg);
+        IN_UPDATE_SZ(img_info->arg_idx);
+        IN_UPDATE_SZ(img_info->idx);
+        IN_UPDATE_SZ(img_info->wSlot);
+        IN_UPDATE_SZ(img_info->hSlot);
+        IN_UPDATE_SZ(img_info->depthSlot);
+        IN_UPDATE_SZ(img_info->dataTypeSlot);
+        IN_UPDATE_SZ(img_info->channelOrderSlot);
+        IN_UPDATE_SZ(img_info->dimOrderSlot);
+
+        imageSet->regMap.insert(std::make_pair(reg, img_info));
+      }
+    }
+
+    IN_UPDATE_SZ(image_map_sz); //indexMap
+    if (image_map_sz){
+      for (uint32_t i = 0; i < image_map_sz; i++) {
+        uint32_t index;
+        ImageInfo *img_info = GBE_NEW(struct ImageInfo);;
+
+        IN_UPDATE_SZ(index);
+        IN_UPDATE_SZ(img_info->arg_idx);
+        IN_UPDATE_SZ(img_info->idx);
+        IN_UPDATE_SZ(img_info->wSlot);
+        IN_UPDATE_SZ(img_info->hSlot);
+        IN_UPDATE_SZ(img_info->depthSlot);
+        IN_UPDATE_SZ(img_info->dataTypeSlot);
+        IN_UPDATE_SZ(img_info->channelOrderSlot);
+        IN_UPDATE_SZ(img_info->dimOrderSlot);
+
+        imageSet->indexMap.insert(std::make_pair(index, img_info));
+      }
+    }
+
+    IN_UPDATE_SZ(code_size);
+    if (code_size) {
+      char * code = GBE_NEW_ARRAY_NO_ARG(char, code_size);
+      ins.read(code, code_size*sizeof(char));
+      total_size -= sizeof(char)*code_size;
+      setCode(code, code_size);
+    }
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_end)
+      return 0;
+
+    if (total_size)
+      return 0;
+
+    return ret_size;
+  }
+
+#undef OUT_UPDATE_SZ
+#undef IN_UPDATE_SZ
+
+ /*********************** End of Program class member function *************************/
+
   static void programDelete(gbe_program gbeProgram) {
     gbe::Program *program = (gbe::Program*)(gbeProgram);
     GBE_SAFE_DELETE(program);
diff --git a/backend/src/backend/program.hpp b/backend/src/backend/program.hpp
index f1ab20e..6d53253 100644
--- a/backend/src/backend/program.hpp
+++ b/backend/src/backend/program.hpp
@@ -67,7 +67,7 @@ namespace gbe {
   }
 
   /*! Describe a compiled kernel */
-  class Kernel : public NonCopyable
+  class Kernel : public NonCopyable, public Serializable
   {
   public:
     /*! Create an empty kernel with the given name */
@@ -76,6 +76,8 @@ namespace gbe {
     virtual ~Kernel(void);
     /*! Return the instruction stream (to be implemented) */
     virtual const char *getCode(void) const = 0;
+    /*! Set the instruction stream.*/
+    virtual const void setCode(const char *, size_t size) = 0;
     /*! Return the instruction stream size (to be implemented) */
     virtual size_t getCodeSize(void) const = 0;
     /*! Get the kernel name */
@@ -128,9 +130,37 @@ namespace gbe {
     size_t getImageSize(void) const { return imageSet->getDataSize(); }
     /*! Get defined image value array */
     void getImageData(ImageInfo *images) const { imageSet->getData(images); }
+
+    static const uint32_t magic_begin = TO_MAGIC('K', 'E', 'R', 'N');
+    static const uint32_t magic_end = TO_MAGIC('N', 'R', 'E', 'K');
+
+    /* format:
+       magic_begin |
+       name_size |
+       name |
+       arg_num |
+       args |
+       PatchInfo_num |
+       PatchInfo |
+       curbeSize |
+       simdWidth |
+       stackSize |
+       useSLM |
+       samplers |
+       images |
+       code_size |
+       code |
+       magic_end
+    */
+
+    /*! Implements the serialization. */
+    virtual size_t serializeToBin(std::ostream& outs);
+    virtual size_t deserializeFromBin(std::istream& ins);
+
+
   protected:
     friend class Context;      //!< Owns the kernels
-    const std::string name;    //!< Kernel name
+    std::string name;    //!< Kernel name
     KernelArgument *args;      //!< Each argument
     vector<PatchInfo> patches; //!< Indicates how to build the curbe
     uint32_t argNum;           //!< Number of function arguments
@@ -146,7 +176,7 @@ namespace gbe {
   };
 
   /*! Describe a compiled program */
-  class Program : public NonCopyable
+  class Program : public NonCopyable, public Serializable
   {
   public:
     /*! Create an empty program */
@@ -186,6 +216,31 @@ namespace gbe {
     size_t getGlobalConstantSize(void) const { return constantSet->getDataSize(); }
     /*! Get the content of global constant arrays */
     void getGlobalConstantData(char *mem) const { constantSet->getData(mem); }
+
+    static const uint32_t magic_begin = TO_MAGIC('P', 'R', 'O', 'G');
+    static const uint32_t magic_end = TO_MAGIC('G', 'O', 'R', 'P');
+
+    /* format:
+       magic_begin | kernel_number | constant_number |
+       const_data_size |
+       const_data |
+       constant_1_size |
+       constant_1 |
+       ........   |
+       constant_n_size |
+       constant_n |
+       kernel_1_size |
+       kernel_1   |
+       ........   |
+       kernel_n_size   |
+       kernel_n   |
+       magic_end
+    */
+
+    /*! Implements the serialization. */
+    virtual size_t serializeToBin(std::ostream& outs);
+    virtual size_t deserializeFromBin(std::istream& ins);
+
   protected:
     /*! Compile a kernel */
     virtual Kernel *compileKernel(const ir::Unit &unit, const std::string &name) = 0;
diff --git a/backend/src/ir/constant.hpp b/backend/src/ir/constant.hpp
index 0717391..a3eab64 100644
--- a/backend/src/ir/constant.hpp
+++ b/backend/src/ir/constant.hpp
@@ -28,6 +28,9 @@
 #include "sys/vector.hpp"
 
 namespace gbe {
+
+class Program;
+
 namespace ir {
 
   /*! Describe one constant (may be a scalar or an array) */
@@ -52,6 +55,8 @@ namespace ir {
     /*! Nothing happens here */
     INLINE ~Constant(void) {}
     const std::string& getName(void) const { return name; }
+    uint32_t getSize (void) const { return size; }
+    uint32_t getAlignment (void) const { return alignment; }
     uint32_t getOffset(void) const { return offset; }
     uint16_t getReg(void) const { return reg; }
     void setReg(uint16_t reg) { this->reg = reg; }
@@ -102,6 +107,7 @@ namespace ir {
       return *this;
     }
   private:
+    friend class gbe::Program;
     vector<char> data;         //!< The constant data serialized in one array
     vector<Constant> constants;//!< Each constant description
     GBE_CLASS(ConstantSet);
diff --git a/backend/src/ir/image.hpp b/backend/src/ir/image.hpp
index 04e78e6..61d9426 100644
--- a/backend/src/ir/image.hpp
+++ b/backend/src/ir/image.hpp
@@ -32,6 +32,8 @@ extern "C" {
 }
 
 namespace gbe {
+  class Kernel;
+
 namespace ir {
 
   class Context;
@@ -61,6 +63,7 @@ namespace ir {
     ImageSet() {}
     ~ImageSet();
   private:
+    friend class gbe::Kernel;
     map<Register, struct ImageInfo *> regMap;
     map<uint32_t, struct ImageInfo *> indexMap;
     GBE_CLASS(ImageSet);
diff --git a/backend/src/ir/sampler.hpp b/backend/src/ir/sampler.hpp
index f968299..bcb6c74 100644
--- a/backend/src/ir/sampler.hpp
+++ b/backend/src/ir/sampler.hpp
@@ -28,6 +28,8 @@
 #include "sys/map.hpp"
 
 namespace gbe {
+  class Kernel;
+
 namespace ir {
 
   /*! A sampler set is a set of global samplers which are defined as constant global
@@ -67,6 +69,7 @@ namespace ir {
     SamplerSet(const SamplerSet& other) : samplerMap(other.samplerMap.begin(), other.samplerMap.end()) { }
     SamplerSet() {}
   private:
+    friend class gbe::Kernel;
     void appendReg(const Register reg, uint32_t key, Context *ctx);
     map<uint32_t, SamplerRegSlot> samplerMap;
     map<Register, SamplerRegSlot> regMap;
diff --git a/backend/src/sys/platform.hpp b/backend/src/sys/platform.hpp
index a665356..8b28b7b 100644
--- a/backend/src/sys/platform.hpp
+++ b/backend/src/sys/platform.hpp
@@ -24,6 +24,9 @@
 #include <cstdlib>
 #include <cstdio>
 #include <iostream>
+#include <ostream>
+#include <istream>
+#include <string>
 #include <cassert>
 #include <new>
 
@@ -323,6 +326,25 @@ private:
   INLINE NonCopyable& operator= (const NonCopyable&) {return *this;}
 };
 
+#define TO_MAGIC(A, B, C, D)  (A<<24 | B<<16 | C<<8 | D)
+
+class Serializable
+{
+public:
+  INLINE Serializable(void) = default;
+
+  /* We do not want to be copied. */
+  INLINE Serializable(const Serializable&) = delete;
+  INLINE Serializable& operator= (const Serializable&) = delete;
+
+  virtual size_t serializeToBin(std::ostream& outs) = 0;
+  virtual size_t deserializeFromBin(std::istream& ins) = 0;
+
+  /* These two will follow LLVM's ABI. */
+  virtual size_t serializeToLLVM(void) { return 0;/* not implemented now. */}
+  virtual size_t deserializeFromLLVM(void) { return 0;/* not implemented now. */}
+};
+
 ////////////////////////////////////////////////////////////////////////////////
 /// Disable some compiler warnings
 ////////////////////////////////////////////////////////////////////////////////
-- 
1.7.9.5



More information about the Beignet mailing list