[CPU] Fix primitive attributes creation for 1x1 Convolution as FC executor (#23272)

### Details:
 - By providing correct output dimensions.

### Tickets:
 - 134466

---------

Co-authored-by: Maksim Kutakov <maksim.kutakov@intel.com>
This commit is contained in:
Egor Duplenskii 2024-03-14 15:21:15 +01:00 committed by GitHub
parent 5dc22c1c18
commit bd734284bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 65 additions and 6 deletions

View File

@ -6,15 +6,17 @@
#include <common/primitive_desc_iface.hpp>
#include <oneapi/dnnl/dnnl.hpp>
#include <vector>
#include "dnnl_extension_utils.h"
#include "memory_desc/cpu_memory_desc.h"
#include "dnnl_postops_composer.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "memory_desc/dnnl_memory_desc.h"
#include "nodes/executors/convolution_config.hpp"
#include "nodes/executors/dnnl/dnnl_aliases.hpp"
#include "nodes/executors/dnnl/dnnl_shape_agnostic_data.hpp"
#include "nodes/executors/executor.hpp"
#include "nodes/executors/fullyconnected_config.hpp"
#include "nodes/executors/memory_arguments.hpp"
#include "onednn/iml_type_mapper.h"
@ -64,7 +66,8 @@ bool DnnlConvolutionPrimitive::Key::operator==(const Key& rhs) const {
}
// make a fake shape: N, C, W
static dnnl::memory::dims normalizeDims(const dnnl::memory::dims& dims) {
template <typename T>
static std::vector<T> normalizeDims(const std::vector<T>& dims) {
assert(one_of(static_cast<int>(dims.size()), 2, 3));
if (dims.size() == 3) {
@ -138,6 +141,47 @@ static primitive_desc createPrimitiveDesc(const dnnl::engine& engine,
return std::move(first_desc);
}
static DnnlPrimitiveAttrs createPrimitiveAttrs(const ConvAttrs& attrs,
const PostOps& postOps,
const MemoryArgs& memory,
ExecutorContext::CPtr context) {
const auto& srcDesc = memory.at(ARG_SRC)->getDescPtr();
const auto& weiDesc = memory.at(ARG_WEI)->getDescPtr();
const auto& dstDesc = memory.at(ARG_DST)->getDescPtr();
const auto& originalDims = dstDesc->getShape().getMinDims();
const auto& dims = normalizeDims(originalDims);
auto isINT8 =
one_of(srcDesc->getPrecision(), ov::element::u8, ov::element::i8) && weiDesc->getPrecision() == ov::element::i8;
auto outputDataType = DnnlExtensionUtils::ElementTypeToDataType(dstDesc->getPrecision());
DnnlPostOpsComposer dnnlpoc(postOps,
context->getEngine(),
dims,
1,
isINT8,
1 << 0,
{},
attrs.withBias,
outputDataType);
return dnnlpoc.compose();
}
DnnlShapeAgnosticDataPtr DnnlConvolutionPrimitive::createShapeAgnosticData(const FCAttrs& attrs,
const PostOps& postOps,
const MemoryArgs& memory,
const ExecutorContext::CPtr context,
const bool cacheWeights) {
DEBUG_LOG("Creating shape agnostic data");
ConvAttrs convAttrs{attrs.withBias};
const auto postOpData = createPrimitiveAttrs(convAttrs, postOps, memory, context);
return std::make_shared<DnnlShapeAgnosticData>(postOpData);
}
void DnnlConvolutionPrimitive::execute(const dnnl_primitive_args& primArgs) const {
m_prim.execute(m_stream, primArgs);
}

View File

@ -7,13 +7,13 @@
#include <memory>
#include <oneapi/dnnl/dnnl.hpp>
#include "cpu_memory.h"
#include "memory_desc/dnnl_memory_desc.h"
#include "nodes/executors/convolution_config.hpp"
#include "nodes/executors/dnnl/dnnl_aliases.hpp"
#include "nodes/executors/dnnl/dnnl_shape_agnostic_data.hpp"
#include "nodes/executors/dnnl/dnnl_utils.hpp"
#include "nodes/executors/executor.hpp"
#include "nodes/executors/fullyconnected_config.hpp"
namespace ov {
namespace intel_cpu {
@ -61,6 +61,13 @@ public:
return m_implType;
}
// create shape agnostic data using FC attributes (1x1 Convolution as FC executor)
static DnnlShapeAgnosticDataPtr createShapeAgnosticData(const FCAttrs& attrs,
const PostOps& postOps,
const MemoryArgs& memory,
const ExecutorContext::CPtr context,
const bool cacheWeights);
static std::shared_ptr<DnnlConvolutionPrimitive> create(const MemoryArgs& memory,
const ConvAttrs& attrs,
const ExecutorContext::CPtr context,

View File

@ -10,6 +10,7 @@
#include "cpu_memory.h"
#include "memory_desc/cpu_memory_desc.h"
#include "nodes/executors/dnnl/dnnl_fullyconnected_primitive.hpp"
#include "nodes/executors/dnnl/dnnl_convolution_primitive.hpp"
#include "nodes/executors/dnnl/dnnl_aliases.hpp"
#include "nodes/executors/executor.hpp"
#include "nodes/executors/executor_config.hpp"
@ -43,7 +44,7 @@ public:
const bool cacheWeights)
: m_attrs(attrs),
m_context(context),
m_shapeAgnosticData(DnnlFCPrimitive::createShapeAgnosticData(m_attrs, postOps, memory, m_context, cacheWeights)),
m_shapeAgnosticData(Primitive::createShapeAgnosticData(m_attrs, postOps, memory, m_context, cacheWeights)),
m_primArgs(m_shapeAgnosticData->primAttrs.dnnlArgs) {}
bool update(const MemoryArgs& memory) override {
const auto primitive = createPrimitive(memory);

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
//
// @file dnnl_utils.hpp
// Contains utility methods supposed used by oneDNN backend executors
// Contains utility methods used by oneDNN backend executors
//
#pragma once

View File

@ -41,6 +41,12 @@ namespace intel_cpu {
# define OV_CPU_INSTANCE_X64(...)
#endif
#if defined(OV_CPU_WITH_MLAS) && defined(OPENVINO_ARCH_X86_64)
# define OV_CPU_INSTANCE_MLAS_X64(...) {__VA_ARGS__},
#else
# define OV_CPU_INSTANCE_MLAS_X64(...)
#endif
#define OV_CPU_INSTANCE_COMMON(...) {__VA_ARGS__},
// @todo another option is to determine shape relation by executor type

View File

@ -146,7 +146,7 @@ OV_CPU_MAYBE_UNUSED_FUNCTION static inline bool noPostOps(const FCConfig& config
template <>
const std::vector<ExecutorImplementation<FCAttrs>>& getImplementations() {
static const std::vector<ExecutorImplementation<FCAttrs>> fullyconnectedImplementations {
OV_CPU_INSTANCE_X64(
OV_CPU_INSTANCE_MLAS_X64(
"fullyconnected_mlas",
ExecutorType::Mlas,
OperationType::MatMul,

View File

@ -191,6 +191,7 @@ std::vector<fusingSpecificParams> fusingParamsSet2D_Brgemm_smoke {
fusingMultiplyPerChannel,
#endif
fusingFakeQuantizePerTensorRelu,
fusingReluScaleShift
};
const auto fullyConnectedParams2D_Brgemm_smoke = ::testing::Combine(::testing::ValuesIn(IS2D_Brgemm_smoke),