Skip to content

Commit

Permalink
Merge pull request PaddlePaddle#56 from Superjomn/refine/runtime-inte…
Browse files Browse the repository at this point in the history
…rface

implement x86 device
  • Loading branch information
Superjomn authored Mar 1, 2020
2 parents 5b91413 + 5a020c8 commit 07bb542
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 28 deletions.
6 changes: 5 additions & 1 deletion cinn/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
set(srcs intrinsic.cc buffer.cc cinn_runtime.cc)
set(srcs intrinsic.cc)

foreach(cpp ${srcs})
set(core_src
"${core_src};cinn/runtime/${cpp}"
CACHE INTERNAL "")
endforeach()

cc_library(cinn_runtime SRCS cinn_runtime.cc buffer.cc cinn_x86_device_impl.cc)

cc_test(test_cinn_runtime SRCS cinn_runtime_test.cc DEPS cinn_runtime)
80 changes: 80 additions & 0 deletions cinn/runtime/cinn_runtime.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "cinn/runtime/cinn_runtime.h"

extern "C" {

int cinn_device_malloc(void* context, struct cinn_buffer_t* buf) {
// ASSERT_NOT_NULL(context)
ASSERT_NOT_NULL(buf)
ASSERT_NOT_NULL(buf->device_interface)
return buf->device_interface->impl->malloc(context, buf);
}

int cinn_device_free(void* context, struct cinn_buffer_t* buf) {
// ASSERT_NOT_NULL(context)
ASSERT_NOT_NULL(buf)
return buf->device_interface->impl->free(context, buf);
}

int cinn_device_sync(void* context, struct cinn_buffer_t* buf) {
ASSERT_NOT_NULL(buf)
ASSERT_NOT_NULL(buf->device_interface)
// ASSERT_NOT_NULL(context)
buf->device_interface->impl->sync(context, buf);
return 0;
}

int cinn_device_release(void* context, const struct cinn_device_interface_t* device_interface) {
// ASSERT_NOT_NULL(context)
ASSERT_NOT_NULL(device_interface)
CINN_NOT_IMPLEMENTED
}

int cinn_copy_to_host(void* context, struct cinn_buffer_t* buf) {
// ASSERT_NOT_NULL(context)
ASSERT_NOT_NULL(buf)
ASSERT_NOT_NULL(buf->device_interface)
return buf->device_interface->impl->copy_to_host(context, buf);
}

int cinn_copy_to_device(void* context, struct cinn_buffer_t* buf) {
// ASSERT_NOT_NULL(context)
ASSERT_NOT_NULL(buf)
ASSERT_NOT_NULL(buf->device_interface)
return buf->device_interface->impl->copy_to_device(context, buf);
}
int cinn_buffer_copy(void* context, struct cinn_buffer_t* src, struct cinn_buffer_t* dst) {
// ASSERT_NOT_NULL(context);
ASSERT_NOT_NULL(src);
ASSERT_NOT_NULL(dst);
return dst->device_interface->buffer_copy(context, src, dst);
}

cinn_type_t cinn_int32_t() { return cinn_type_t(cinn_type_int, 32); }
cinn_type_t cinn_int64_t() { return cinn_type_t(cinn_type_int, 64); }
cinn_type_t cinn_uint32_t() { return cinn_type_t(cinn_type_uint, 32); }
cinn_type_t cinn_uint64_t() { return cinn_type_t(cinn_type_uint, 64); }
cinn_type_t cinn_float32_t() { return cinn_type_t(cinn_type_float, 32); }
cinn_type_t cinn_float64_t() { return cinn_type_t(cinn_type_float, 64); }

} // extern "C"

struct cinn_buffer_t* cinn_buffer_t::new_(cinn_device_kind_t device, cinn_type_t type) {
struct cinn_buffer_t* x = new (struct cinn_buffer_t);
x->type = type;
x->device = device;
// NOTE set device_interface for each buffer.
switch (x->device) {
case cinn_x86_device:
x->device_interface = &cinn_x86_device_interface;
break;
case cinn_unk_device:
fprintf(stderr, "Device type of buffer should be set, found Unk");
abort();
break;
default:
fprintf(stderr, "Not supported device type");
abort();
}

return x;
}
126 changes: 99 additions & 27 deletions cinn/runtime/cinn_runtime.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
#ifndef CINN_RUNTIME_H_
#define CINN_RUNTIME_H_
#ifndef CINN_RUNTIME_CINN_RUNTIME_H_
#define CINN_RUNTIME_CINN_RUNTIME_H_

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

#define CINN_ALWAYS_INLINE __attribute__((always_inline)) inline

//! Code for the primitive types supported in CINN.
typedef enum cinn_type_code_t {
cinn_type_int = 0, //! signed int
cinn_type_uint = 1, //! unsigned int
Expand Down Expand Up @@ -50,10 +54,27 @@ typedef struct cinn_type_t {

} cinn_type_t;

//! Some primitive types.
// @{
extern cinn_type_t cinn_int32_t();
extern cinn_type_t cinn_int64_t();
extern cinn_type_t cinn_uint32_t();
extern cinn_type_t cinn_uint64_t();
extern cinn_type_t cinn_float32_t();
extern cinn_type_t cinn_float64_t();
// @}

//! Help to define the size of a dimension, due to polyhedral representation, we no need to record the extend or
//! min(default to 0).
typedef int cinn_dimension_t;

//! Help to tell the kind of the device.
typedef enum cinn_device_kind_t {
cinn_unk_device = -1, // Undefined device.
cinn_x86_device = 0, // X86 device
cinn_opencl_device = 1 // OpenCL device
} cinn_device_kind_t;

//! Help to tell where the buffer locates.
typedef enum cinn_buffer_kind_t {
cinn_buffer_on_host = 0, //! buffer on host
Expand All @@ -68,56 +89,45 @@ struct cinn_buffer_t;
struct cinn_device_interface_impl_t;

struct cinn_device_interface_t {
int (*malloc)(void* context, struct cinn_buffer_t* buf, const struct cinn_device_interface_t* device_interface);
int (*free)(void* context, struct cinn_device_interface_t* buf);
int (*malloc)(void* context, struct cinn_buffer_t* buf);
int (*free)(void* context, struct cinn_buffer_t* buf);
int (*sync)(void* context, struct cinn_buffer_t* buf);
void (*release)(void* context, const struct cinn_device_interface_t* device_interface);
int (*release)(void* context, const struct cinn_device_interface_t* device_interface);
int (*copy_to_host)(void* context, struct cinn_buffer_t* buf);
int (*copy_to_device)(void* context,
struct cinn_buffer_t* buf,
const struct cinn_device_interface_t* device_interface);
int (*buffer_copy)(void* context,
struct cinn_buffer_t* src,
struct cinn_buffer_t* dst,
const struct cinn_device_interface_t* dest_device_interface);
int (*copy_to_device)(void* context, struct cinn_buffer_t* buf);
int (*buffer_copy)(void* context, struct cinn_buffer_t* src, struct cinn_buffer_t* dst);
cinn_device_interface_impl_t* impl;
};

/**
* Release all data associated with the given interface.
*/
extern void cinn_device_release(void* context, const struct cinn_device_interface_t* device_interface);
extern int cinn_device_release(void* context, const struct cinn_device_interface_t* device_interface);

/*
* Copy image data from device to host memory.
*/
extern int cinn_copy_to_host(void* context, struct cinn_buffer_t* buf);

//! Copy data from host to device memory.
extern int cinn_copy_to_device(void* context,
struct cinn_buffer_t* buf,
const struct cinn_device_interface_t* device_interface);
extern int cinn_copy_to_device(void* context, struct cinn_buffer_t* buf);

//! Copy data from one buffer to another.
extern int cinn_buffer_copy(void* context,
struct cinn_buffer_t* src,
struct cinn_buffer_t* dst,
const struct cinn_device_interface_t* dest_device_interface);
extern int cinn_buffer_copy(void* context, struct cinn_buffer_t* src, struct cinn_buffer_t* dst);

//! Wait for current device operations to complete.
extern int cinn_device_sync(void* context, struct cinn_buffer_t* buf);

//! Allocate device memory.
extern int cinn_device_malloc(void* context,
struct cinn_buffer_t* buf,
const struct cinn_device_interface_t* device_interface);
extern int cinn_device_malloc(void* context, struct cinn_buffer_t* buf);

//! Free device memory.
extern int cinn_device_free(void* context, struct cinn_buffer_t* buf);

//! The raw representation of a buffer,used in the generated code/lib.
typedef struct cinn_buffer_t {
//! A device handle.
uint64_t device;
//! Tell which kind of device this buffer locates.
cinn_device_kind_t device;

//! The interface used to operate on device.
const struct cinn_device_interface_t* device_interface;
Expand All @@ -135,12 +145,36 @@ typedef struct cinn_buffer_t {
int32_t dimensions;
cinn_dimension_t* dims;

//! The actual memory size.
uint64_t memory_size;

#ifdef __cplusplus
static struct cinn_buffer_t* new_() { return new (struct cinn_buffer_t); }
cinn_buffer_t()
: device(cinn_unk_device),
device_interface(NULL),
host_memory(NULL),
flag(0UL),
type(cinn_type_t()),
dimensions(0),
dims(NULL),
memory_size(0) {}

static struct cinn_buffer_t* new_(cinn_device_kind_t device, cinn_type_t type);
static void delete_(struct cinn_buffer_t* x) { delete x; }

// NOTE the buffer should be resized first.
static void alloc(struct cinn_buffer_t*);

//! Set the shape of the buffer. NOTE this just record the shape, not allocate the memory.
CINN_ALWAYS_INLINE void resize(const cinn_dimension_t* dims, int dimensions) {
if (this->dimensions != dimensions) {
if (this->dims) free(this->dims);
this->dims = (cinn_dimension_t*)malloc(dimensions * sizeof(cinn_dimension_t));
}
this->dimensions = dimensions;
memcpy(this->dims, dims, dimensions * sizeof(cinn_dimension_t));
}

CINN_ALWAYS_INLINE int num_elements() const {
int res = 1;
for (int i = 0; i < dimensions; i++) {
Expand Down Expand Up @@ -176,8 +210,46 @@ typedef struct cinn_buffer_t {

} cinn_buffer_t;

struct cinn_device_interface_impl_t {
int (*malloc)(void* context, struct cinn_buffer_t* buf);
int (*free)(void* context, struct cinn_buffer_t* buf);
int (*sync)(void* context, struct cinn_buffer_t* buf);
int (*release)(void* context);
int (*copy_to_host)(void* context, struct cinn_buffer_t* buf);
int (*copy_to_device)(void* context, struct cinn_buffer_t* buf);
int (*buffer_copy)(void* context, struct cinn_buffer_t* src, struct cinn_buffer_t* dst);
};

// The device implementations
extern cinn_device_interface_t cinn_x86_device_interface;

#ifdef __cplusplus
} // extern "C"
#endif

#endif // CINN_RUNTIME_H_
#define CINN_NOT_IMPLEMENTED \
fprintf(stderr, "Not Implemented!"); \
abort();

#define ASSERT_NOT_NULL(v__) \
if (!v__) { \
fprintf(stderr, #v__ " is null"); \
return -1; \
}
#define CINN_LOG(fmt, ...) \
do { \
fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); \
} while (0)

#define CINN_CHECK(cond) \
if (!(cond)) { \
CINN_LOG("check %s failed", #cond); \
abort(); \
}
#define CINN_CHECKP(cond, ...) \
if (!(cond)) { \
CINN_LOG(__VA_ARGS__); \
abort(); \
}

#endif // CINN_RUNTIME_CINN_RUNTIME_H_
13 changes: 13 additions & 0 deletions cinn/runtime/cinn_runtime_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "cinn/runtime/cinn_runtime.h"

#include <gtest/gtest.h>

TEST(buffer, basic) {
auto* buffer = cinn_buffer_t::new_(cinn_x86_device, cinn_float32_t());
ASSERT_TRUE(buffer);
ASSERT_TRUE(buffer->device_interface);
ASSERT_EQ(buffer->device_interface, &cinn_x86_device_interface);
std::vector<cinn_dimension_t> shape({3, 10});
buffer->resize(shape.data(), shape.size());
buffer->device_interface->impl->malloc(NULL, buffer);
}
56 changes: 56 additions & 0 deletions cinn/runtime/cinn_x86_device_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "cinn/runtime/cinn_runtime.h"

int cinn_x86_malloc(void* context, cinn_buffer_t* buf) {
// ASSERT_NOT_NULL(context)
ASSERT_NOT_NULL(buf)
uint64_t memory_size = buf->num_elements() * buf->type.bytes();
CINN_CHECK(memory_size > 0);
if (buf->memory_size < memory_size) {
if (buf->host_memory) {
free(buf->host_memory);
}
buf->host_memory = (unsigned char*)malloc(buf->type.bytes() * buf->num_elements());
buf->memory_size = memory_size;
CINN_LOG("buf.memory size is %d", buf->memory_size);
}
ASSERT_NOT_NULL(buf->host_memory);
return 0;
}

int cinn_x86_free(void* context, cinn_buffer_t* buf) {
// ASSERT_NOT_NULL(context);
ASSERT_NOT_NULL(buf);
if (buf->host_memory) {
free(buf->host_memory);
buf->host_memory = NULL;
}
return 0;
}

// All the following operations are not support by X86 device, just leave them empty.
// @{
int cinn_x86_sync(void* context, cinn_buffer_t* buf) { return 0; }
int cinn_x86_release(void* context) { return 0; }
int cinn_x86_copy_to_host(void* context, cinn_buffer_t* buf) { return 0; }
int cinn_x86_copy_to_device(void* context, cinn_buffer_t* buf) { return 0; }
int cinn_x86_buffer_copy(void* context, cinn_buffer_t* src, cinn_buffer_t* dst) { return 0; }
// @}

cinn_device_interface_impl_t cinn_x86_device_impl{&cinn_x86_malloc,
&cinn_x86_free,
&cinn_x86_sync,
&cinn_x86_release,
&cinn_x86_copy_to_host,
&cinn_x86_copy_to_device,
&cinn_x86_buffer_copy

};

cinn_device_interface_t cinn_x86_device_interface{&cinn_device_malloc,
&cinn_device_free,
&cinn_device_sync,
&cinn_device_release,
&cinn_copy_to_host,
&cinn_copy_to_device,
&cinn_buffer_copy,
&cinn_x86_device_impl};

0 comments on commit 07bb542

Please sign in to comment.