blob: 7682fe1c1f37957a4ca7ada350349d41dd2a6b09 [file] [log] [blame]
/*******************************************************************************
* Copyright 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \file mkl_memory.cc
* \brief
* \author lingyan.guo@intel.com
* zhenlin.luo@intel.com
*
*******************************************************************************/
#include "../operator_common.h"
#if MXNET_USE_MKL2017 == 1
#include <mkl_memory.h>
#include "mkl_memory-inl.h"
#include "mkl_util-inl.h"
namespace mxnet {
template <typename Dtype>
void MKLMemoryDescriptorBase<Dtype>::create_conversions() {
int status;
if (this->convert_from_int) {
status = dnnDelete<Dtype>(this->convert_from_int);
CHECK_EQ(status, E_SUCCESS);
this->convert_from_int = NULL;
}
if (this->convert_to_int) {
status = dnnDelete<Dtype>(this->convert_to_int);
CHECK_EQ(status, E_SUCCESS);
this->convert_to_int = NULL;
}
if (layout_int
&& !dnnLayoutCompare<Dtype>(layout_usr, layout_int)) {
CHECK(layout_usr);
status = dnnConversionCreate<Dtype>(&convert_to_int, layout_usr,
layout_int);
CHECK_EQ(status, E_SUCCESS)
<< "Failed creation convert_to_int with status "
<< status << " for buffer: " << this->name << "\n";
status = dnnConversionCreate<Dtype>(&convert_from_int, layout_int,
layout_usr);
CHECK_EQ(status, E_SUCCESS)
<< "Failed creation convert_from_int with status "
<< status << " for buffer: " << this->name << "\n";
}
}
template <typename Dtype>
void MKLMemoryDescriptorBase<Dtype>::create_internal_layout(
const dnnPrimitive_t primitive, dnnResourceType_t type) {
int status;
if (this->layout_int) {
status = dnnLayoutDelete<Dtype>(this->layout_int);
CHECK_EQ(status, E_SUCCESS);
}
status = dnnLayoutCreateFromPrimitive<Dtype>(
&this->layout_int, primitive, type);
CHECK_EQ(status, E_SUCCESS)
<< "Failed dnnLayoutCreateFromPrimitive with status "
<< status << " for buffer: " << this->name << "\n";
if (this->layout_usr)
this->create_conversions();
}
template <typename Dtype>
void MKLMemoryDescriptorBase<Dtype>::create_user_layout(
size_t dimension, const size_t size[], const size_t strides[]) {
int status;
if (this->layout_usr) {
status = dnnLayoutDelete<Dtype>(this->layout_usr);
CHECK_EQ(status, E_SUCCESS);
}
status = dnnLayoutCreate<Dtype>(
&this->layout_usr, dimension, size, strides);
CHECK_EQ(status, E_SUCCESS) << "Failed dnnLayoutCreate with status "
<< status << " for buffer: " << this->name << "\n";
if (this->layout_int)
this->create_conversions();
}
template <typename Dtype>
void MKLMemoryDescriptorBase<Dtype>::create_layouts(
const dnnPrimitive_t primitive, dnnResourceType_t type,
size_t dimension, const size_t size[], const size_t strides[]) {
this->create_internal_layout(primitive, type);
this->create_user_layout(dimension, size, strides);
}
template <typename Dtype>
void MKLMemoryDescriptorBase<Dtype>::convert_from_prv(void* cpu_ptr) {
CHECK(cpu_ptr);
CHECK(this->convert_from_int);
int status;
void *convert_resources[dnnResourceNumber];
convert_resources[dnnResourceFrom] = this->prv_ptr();
convert_resources[dnnResourceTo] = cpu_ptr;
status = dnnExecute<Dtype>(this->convert_from_int, convert_resources);
CHECK_EQ(status, 0) << "Conversion from prv failed with status " << status;
}
template <typename Dtype>
void MKLMemoryDescriptorBase<Dtype>::convert_to_prv(void* cpu_ptr) {
CHECK(cpu_ptr);
CHECK(this->convert_to_int);
int status;
void *convert_resources[dnnResourceNumber];
convert_resources[dnnResourceFrom] = cpu_ptr;
convert_resources[dnnResourceTo] = this->prv_ptr();
status = dnnExecute<Dtype>(this->convert_to_int, convert_resources);
CHECK_EQ(status, 0) << "Conversion from prv failed with status " << status;
}
template <typename Dtype>
bool MKLMemoryDescriptorBase<Dtype>::layout_compare(
std::shared_ptr<PrvMemDescr> other) {
CHECK_EQ(other->get_descr_type(),
PrvMemDescr::PRV_DESCR_MKL2017);
std::shared_ptr<MKLMemoryDescriptorBase<Dtype> >other_descr =
std::static_pointer_cast<MKLMemoryDescriptorBase<Dtype> >
(other);
if (dnnLayoutCompare<Dtype>(other_descr->layout_int,
this->layout_int))
return true;
else
return false;
}
template <typename Dtype>
void MKLMemoryDescriptorBase<Dtype>::convert_from_other(
std::shared_ptr<PrvMemDescr> other) {
std::shared_ptr<MKLMemoryDescriptorBase<Dtype> > other_descr =
std::static_pointer_cast<MKLMemoryDescriptorBase<Dtype> >
(other);
int status;
dnnPrimitive_t convert;
status = dnnConversionCreate<Dtype>(&convert,
other_descr->layout_int, this->layout_int);
void *convert_resources[dnnResourceNumber];
convert_resources[dnnResourceFrom] = other_descr->prv_ptr();
convert_resources[dnnResourceTo] = this->prv_ptr();
status = dnnExecute<Dtype>(convert, convert_resources);
CHECK_EQ(status, 0) << "Conversion from other failed with status "
<< status;
dnnDelete<Dtype>(convert);
}
template <typename Dtype>
Dtype* MKLMemoryDescriptor<Dtype>::get_converted_prv(
Dtype *cpu_ptr, bool set_prv_ptr, const TBlob &blob) {
Dtype* prv_ptr = NULL;
std::shared_ptr<MKLMemHolder> dnn_chunk = NULL;
#if MKL_EXPERIMENTAL == 1
dnn_chunk = blob.Mkl_mem_;
#endif
#if MKL_EXPERIMENTAL == 1
if (dnn_chunk != NULL)
prv_ptr = static_cast<Dtype*>(dnn_chunk->prv_data());
#endif
if (this->convert_to_int != NULL) {
#if MKL_EXPERIMENTAL == 1
int status;
void *convert_resources[dnnResourceNumber];
#endif
if (prv_ptr == NULL) {
this->allocate();
this->convert_to_prv(cpu_ptr);
#if MKL_EXPERIMENTAL == 1
if (set_prv_ptr) {
dnn_chunk->set_prv_descriptor(this->get_shared_ptr(), true);
}
#endif
return this->internal_ptr;
}
#if MKL_EXPERIMENTAL == 1
if (prv_ptr != NULL) {
std::shared_ptr<MKLData<Dtype> > current_descr =
op::mkl_get_mem_desc<Dtype>(dnn_chunk);
if (!dnnLayoutCompare<Dtype>(current_descr->layout_int,
this->layout_int)) {
if (this->convert_prv2prv) {
CHECK_EQ(dnnLayoutCompare<Dtype>(
this->descr_prv2prv_conversion->layout_int,
this->layout_int), 0);
status = 0;
} else {
status = dnnConversionCreate<Dtype>(&this->convert_prv2prv,
current_descr->layout_int, this->layout_int);
if (status == 0)
this->descr_prv2prv_conversion = current_descr;
}
if (status != 0) {
this->allocate();
convert_resources[dnnResourceFrom] = cpu_ptr;
convert_resources[dnnResourceTo] =
reinterpret_cast<void*>(this->internal_ptr);
status = dnnExecute<Dtype>(this->convert_to_int, convert_resources);
CHECK_EQ(status, 0) << "Conversion failed with status " << status;
} else {
this->allocate();
convert_resources[dnnResourceFrom] = reinterpret_cast<void*>(prv_ptr);
convert_resources[dnnResourceTo] =
reinterpret_cast<void*>(this->internal_ptr);
status = dnnExecute<Dtype>(this->convert_prv2prv, convert_resources);
CHECK_EQ(status, 0) << "Conversion failed with status " << status;
}
if (set_prv_ptr) {
dnn_chunk->set_prv_descriptor(this->get_shared_ptr(), true);
}
return this->internal_ptr;
} else if (current_descr.get() != this) {
// MKL_DLOG(INFO) << "layout OK "
// << current_descr->name << " == " << this->name;
}
}
#endif
return const_cast<Dtype *>(prv_ptr);
} else {
if (prv_ptr != NULL) {
#if MKL_EXPERIMENTAL == 1
std::shared_ptr<MKLMemoryDescriptorBase<float> > other_descr =
std::static_pointer_cast<MKLMemoryDescriptorBase<float> >
(dnn_chunk->prv_descriptor_);
dnn_chunk->check_and_prv_to_cpu(cpu_ptr);
#endif
// printf("get_converted_prv release %s\n", other_descr->name.c_str());
}
}
return cpu_ptr;
}
template <typename Dtype>
void* MKLMemoryDescriptor<Dtype>::get_output_ptr(Dtype *data_ptr,
std::shared_ptr<MKLMemoryDescriptor<Dtype> > self_ptr, const TBlob &blob, bool in_place) {
#if MKL_EXPERIMENTAL == 1
std::shared_ptr<MKLMemHolder> dnn_chunk = blob.Mkl_mem_;
#endif
if (this->conversion_needed()) {
void * prv_ptr = this->prv_ptr();
#if MKL_EXPERIMENTAL == 1
if (!in_place) {
dnn_chunk->set_prv_descriptor(self_ptr);
} else {
Dtype * blob_prv = op::mkl_prv_data<Dtype>(blob);
if (blob_prv != NULL)
return blob_prv;
}
#endif
return prv_ptr;
} else {
#if MKL_EXPERIMENTAL == 1
std::shared_ptr<MKLMemoryDescriptorBase<float> > other_descr =
std::static_pointer_cast<MKLMemoryDescriptorBase<float> >
(dnn_chunk->prv_descriptor_);
dnn_chunk->check_and_prv_to_cpu(data_ptr);
#endif
return data_ptr;
}
}
template class MKLMemoryDescriptor<double>;
template class MKLMemoryDescriptor<float>;
template class MKLMemoryDescriptorBase<float>;
template class MKLMemoryDescriptorBase<double>;
} // namespace mxnet
#endif