diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d82a7af8..c7b5db247 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,12 +96,12 @@ if(GC_ENABLE_BINDINGS_PYTHON) endif() set(GC_LIB_LINKED_LIBS - GCPasses - MLIROneDNNGraph + GCJitWrapper + GCCpuRuntime ) -add_library(graph_compiler SHARED ${GC_LIB_SOURCES}) +add_mlir_library(graph_compiler SHARED ${GC_LIB_SOURCES}) target_include_directories(graph_compiler PUBLIC ${GC_LIB_INCLUDES}) -target_compile_options(graph_compiler PRIVATE -fvisibility=hidden) +target_compile_options(graph_compiler PRIVATE -fvisibility=hidden -fexceptions) target_link_options(graph_compiler PRIVATE -Wl,--gc-sections) target_link_libraries(graph_compiler PRIVATE ${GC_LIB_LINKED_LIBS}) diff --git a/src/dnnl/JsonParser.cpp b/src/dnnl/JsonParser.cpp index 1c0e15b94..bb2e0c221 100644 --- a/src/dnnl/JsonParser.cpp +++ b/src/dnnl/JsonParser.cpp @@ -23,6 +23,7 @@ #include "gc/Dialect/OneDNNGraph/OneDNNGraphDialect.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/ExecutionEngine/OptUtils.h" #include "mlir/IR/Builders.h" #include "mlir/IR/MLIRContext.h" @@ -30,8 +31,10 @@ #include "JsonParser.h" -mlir::ModuleOp JsonParser::parse() { - std::vector inputPorts; +mlir::ModuleOp +JsonParser::parse(llvm::SmallVector &outputIds, + std::unordered_map &strides) { + llvm::SmallVector inputPorts; bool hasInputPorts = false; bool hasOutputPorts = false; _reader.begin_object(); @@ -57,7 +60,7 @@ mlir::ModuleOp JsonParser::parse() { readNumArray(inputPorts); } else if (_str == "output_ports") { hasOutputPorts = true; - readNumArray(_outputIds); + readNumArray(outputIds); } else if (_str == "graph") { _reader.begin_array(); while (_reader.next_array_item()) { @@ -87,13 +90,13 @@ mlir::ModuleOp JsonParser::parse() { if (!hasOutputPorts) { // If output_ports is not specified, using the last operation's outputs. - _outputIds = _uaS; + outputIds.append(_uaS.begin(), _uaS.end()); } // The function return values. - std::vector outputs; - outputs.reserve(_outputIds.size()); - for (auto id : _outputIds) { + llvm::SmallVector outputs; + outputs.reserve(outputIds.size()); + for (auto id : outputIds) { auto entry = _valueMap.find(id); if (entry == _valueMap.end()) { _str = std::to_string(id); @@ -103,13 +106,25 @@ mlir::ModuleOp JsonParser::parse() { } auto ret = _builder.create(_loc, outputs); + // Copying the strides for the inputs and outputs. + for (auto &ids : {&_inputIds, &outputIds}) { + for (auto id : *ids) { + auto entry = _strides.find(id); + if (entry != _strides.end()) { + strides[id] = entry->second; + } + } + } + // Creating the final function and moving the entry block. mlir::OpBuilder builder(_builder.getContext()); auto module = builder.create(_loc); auto func = builder.create( - _loc, "main", + _loc, "compute", builder.getFunctionType(_entryBlock->getArgumentTypes(), ret->getOperandTypes())); + func->setAttr(mlir::LLVM::LLVMDialect::getEmitCWrapperAttrName(), + mlir::UnitAttr::get(_builder.getContext())); auto entry = func.addEntryBlock(); _entryBlock->moveBefore(entry); entry->erase(); @@ -251,7 +266,9 @@ inline mlir::Attribute JsonParser::readAttr() { mlir::Type JsonParser::readTensorType() { GetTypeFn getTypeFn = nullptr; + bool strided = false; _ia64.clear(); + _ia642.clear(); _reader.begin_object(); while (_reader.next_object_item(&_str)) { @@ -267,22 +284,17 @@ mlir::Type JsonParser::readTensorType() { } else if (_str == "shape") { readNumArray(_ia64); } else if (_str == "stride") { - _ia642.clear(); readNumArray(_ia642); - if ((_ia642.size() > 1) || - ((_ia642.size() == 1) && - (_ia642[0] != std::numeric_limits::min()))) { - // TODO: Add support for strides - throwErr("Unsupported stride value: "); - } } else if (_str == "layout_type") { _reader.read_string(&_str); - if ((_str != "undef") && (_str != "any")) { + if (_str == "strided") { + strided = true; + } else if ((_str != "undef") && (_str != "any")) { throwErr("Unsupported layout_type: "); } } else if (_str == "property_type") { _reader.read_string(&_str); - if ((_str != "undef") && (_str != "constant")) { + if ((_str != "undef") && (_str != "variable") && (_str != "constant")) { throwErr("Unsupported property_type: "); } } else { @@ -295,6 +307,10 @@ mlir::Type JsonParser::readTensorType() { throwErr("dtype is not specified"); } + if (strided) { + _strides[_uS].assign(_ia642.begin(), _ia642.end()); + } + if ((_ia64.size() == 1) && (_ia64[0] == std::numeric_limits::min())) { return mlir::UnrankedTensorType::get(getTypeFn(_builder)); diff --git a/src/dnnl/JsonParser.h b/src/dnnl/JsonParser.h index c11a616a9..d9fcb9a6f 100644 --- a/src/dnnl/JsonParser.h +++ b/src/dnnl/JsonParser.h @@ -43,22 +43,25 @@ using float32_t = float; #include "mlir/Parser/Parser.h" #include "mlir/Tools/mlir-opt/MlirOptMain.h" +#include "dnnl_types.h" #include "graph/utils/json.hpp" +using Strides = llvm::SmallVector; + class JsonParser { dnnl::impl::graph::utils::json::json_reader_t _reader; mlir::OpBuilder _builder; mlir::Location _loc; mlir::Block *_entryBlock; - std::vector &_inputIds; - std::vector &_outputIds; + llvm::SmallVector &_inputIds; + std::unordered_map _strides; // Function input and operations output values. Used to connect the // operations inputs and outputs. std::unordered_map _valueMap; // Temporary value holders, used by the parser - std::vector _operands; - std::vector _resultTypes; - std::vector _attributes; + llvm::SmallVector _operands; + llvm::SmallVector _resultTypes; + llvm::SmallVector _attributes; std::string _str; std::string _str2; std::size_t _uS; @@ -70,9 +73,9 @@ class JsonParser { std::vector _fa32; JsonParser(mlir::MLIRContext &context, std::istream &stream, - std::vector &inputIds, std::vector &outputIds) + llvm::SmallVector &inputIds) : _reader(&stream), _builder(&context), _loc(_builder.getUnknownLoc()), - _inputIds(inputIds), _outputIds(outputIds), _valueMap(), _operands(), + _inputIds(inputIds), _strides(), _valueMap(), _operands(), _resultTypes(), _attributes(), _str(), _str2(), _uS(), _i64(), _f32(), _uaS(), _ia64(), _ia642(), _fa32() { // Creating a dummy function since we don't know the actual type yet. @@ -82,7 +85,8 @@ class JsonParser { _builder.setInsertionPointToStart(_entryBlock); } - mlir::ModuleOp parse(); + mlir::ModuleOp parse(llvm::SmallVector &outputIds, + std::unordered_map &strides); void readOp(); mlir::Attribute readAttr(); mlir::Type readTensorType(); @@ -120,11 +124,12 @@ class JsonParser { } } - template inline void readNumArray(std::vector &vec) { + template class Container, typename... Any> + inline void readNumArray(Container &c) { _reader.begin_array(); for (T value; _reader.next_array_item();) { _reader.read_number(&value); - vec.push_back(value); + c.push_back(value); } } @@ -175,14 +180,16 @@ class JsonParser { * @param json JSON string containing the oneDNN graph. * @param inputIds Input tensor IDs are added to this vector. * @param outputIds Output tensor IDs are added to this vector. + * @param strides Strides for each tensor are added to this map. * @return The resulting MLIR module. */ - static mlir::ModuleOp parse(mlir::MLIRContext &context, - const std::string_view &json, - std::vector &inputIds, - std::vector &outputIds) { + static mlir::ModuleOp + parse(mlir::MLIRContext &context, const std::string_view &json, + llvm::SmallVector &inputIds, + llvm::SmallVector &outputIds, + std::unordered_map &strides) { std::istringstream stream(json.data()); - JsonParser parser(context, stream, inputIds, outputIds); - return parser.parse(); + JsonParser parser(context, stream, inputIds); + return parser.parse(outputIds, strides); } }; diff --git a/src/dnnl/dnnl_graph_compiler.cpp b/src/dnnl/dnnl_graph_compiler.cpp index d79117b4e..4e214a2ef 100644 --- a/src/dnnl/dnnl_graph_compiler.cpp +++ b/src/dnnl/dnnl_graph_compiler.cpp @@ -21,13 +21,11 @@ #include #include "JsonParser.h" -#include "gc/Dialect/OneDNNGraph/OneDNNGraphDialect.h" -#include "gc/Transforms/Passes.h" +#include "gc/ExecutionEngine/Driver/Driver.h" #include "gc_version.h" +#include "mlir/ExecutionEngine/MemRefUtils.h" #include "mlir/IR/MLIRContext.h" -#include "mlir/InitAllPasses.h" -#include "mlir/Pass/PassManager.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/ThreadPool.h" @@ -43,54 +41,122 @@ // dnnl_graph_compiler.h interface implementation. +using namespace mlir; + +extern "C" { +extern int gc_runtime_keep_alive; +} + struct dnnl_graph_compiler_executable { - // TODO: Implement + dnnl_graph_compiler_executable(MLIRContext &context, + const std::string_view &json) + : inputIds(), outputIds(), jmod() { + auto mod = JsonParser::parse(context, json, inputIds, outputIds, strides); + auto jmod = gc::JitModule::create(mod); + + if (!static_cast(jmod)) { + auto err = jmod.takeError(); + llvm::errs() << err; + llvm::consumeError(std::move(err)); + std::string msg("Failed to create JitModule: "); + llvm::raw_string_ostream(msg) << err; + throw std::runtime_error(msg); + } + + this->jmod = *jmod; + } void execute(dnnl_graph_compiler_tensor *inputs, - dnnl_graph_compiler_tensor *outputs) const; + dnnl_graph_compiler_tensor *outputs) const { + std::vector memRefs; + memRefs.reserve(inputIds.size() + outputIds.size()); + for (auto &pair : {std::make_pair(&inputIds, inputs), + std::make_pair(&outputIds, outputs)}) { + auto ids = pair.first; + auto tensors = pair.second; + for (size_t i = 0, n = ids->size(); i < n; i++) { + auto id = (*ids)[i]; + dnnl_graph_compiler_tensor *tensor; + + if (tensors[i].id == id) { + tensor = &tensors[i]; + } else { + // The order of inputs/outputs may not match the function args order. + tensor = nullptr; + for (size_t j = 0; j < n; j++) { + if (tensors[j].id == id) { + tensor = &tensors[j]; + break; + } + } + if (!tensor) { + throw std::invalid_argument("Tensor not found"); + } + } + + auto s = strides.find((*ids)[i]); + memRefs.emplace_back(tensor, s == strides.end() ? nullptr : &s->second); + } + } + + llvm::SmallVector ptrs; + ptrs.reserve(memRefs.size()); + for (auto &memRef : memRefs) { + ptrs.push_back(&memRef); + } + jmod->call(ptrs.data(), ptrs.size()); + } + +private: + llvm::SmallVector inputIds; + llvm::SmallVector outputIds; + std::unordered_map strides; + std::shared_ptr jmod; + + // C-compatible data wrapper - + // https://mlir.llvm.org/docs/TargetLLVMIR/#c-compatible-wrapper-emission + struct MemRefWrapper { + void *basePtr; + void *data; + int64_t offset = 0; + int64_t dimsAndStrides[2 * DNNL_MAX_NDIMS]; + + MemRefWrapper(dnnl_graph_compiler_tensor *tensor, const Strides *strides) + // We assume, that the data is aligned, thus basePtr == data. + : basePtr(tensor->data), data(tensor->data) { + if (tensor->ndims > DNNL_MAX_NDIMS) { + throw std::invalid_argument("Number of dimensions > DNNL_MAX_NDIMS"); + } + + std::copy(tensor->dims, tensor->dims + tensor->ndims, dimsAndStrides); + if (strides) { + std::copy(strides->begin(), strides->end(), + dimsAndStrides + tensor->ndims); + } else { + for (int64_t d = tensor->ndims - 1, stride = 1; d >= 0; d--) { + dimsAndStrides[tensor->ndims + d] = stride; + stride *= tensor->dims[d]; + } + } + } + }; }; struct dnnl_graph_compiler { + mutable MLIRContext context; + explicit dnnl_graph_compiler(llvm::ThreadPoolStrategy &tps) - : context(RegistryHolder::get(), mlir::MLIRContext::Threading::DISABLED), + : context(gc::initCompilerAndGetDialects(), + MLIRContext::Threading::DISABLED), threadPool(tps) { context.setThreadPool(threadPool); context.loadAllAvailableDialects(); - } - - [[nodiscard]] std::unique_ptr - compile(const std::string_view &json) const { - std::vector inputIds; - std::vector outputIds; - // mlir::ModuleOp module = - JsonParser::parse(context, json, inputIds, outputIds); - - // TODO: Compile the module - - return std::unique_ptr( - new dnnl_graph_compiler_executable()); + // FIXME: keeps GCCPURuntime linked + gc_runtime_keep_alive = 0; } private: - mutable mlir::MLIRContext context; llvm::DefaultThreadPool threadPool; - - class RegistryHolder { - mlir::DialectRegistry registry; - RegistryHolder() : registry() { - mlir::gc::registerGraphCompilerPasses(); - registry.insert(); - registry.insert(); - registry.insert(); - registry.insert(); - } - - public: - static const mlir::DialectRegistry &get() { - static RegistryHolder holder; - return holder.registry; - } - }; }; GC_DLL_EXPORT const dnnl_graph_compiler_version * @@ -130,8 +196,8 @@ GC_DLL_EXPORT dnnl_status_t dnnl_graph_compiler_compile( const dnnl_graph_compiler *gc, const char *graph_json, const struct dnnl_graph_compiler_executable **exe) { try { - auto ptr = gc->compile(std::string_view(graph_json)); - *exe = ptr.release(); + *exe = new dnnl_graph_compiler_executable(gc->context, + std::string_view(graph_json)); return dnnl_success; } catch (const std::invalid_argument &e) { return dnnl_invalid_graph; @@ -163,9 +229,3 @@ GC_DLL_EXPORT dnnl_status_t dnnl_graph_compiler_execute( return dnnl_runtime_error; } } - -void dnnl_graph_compiler_executable::execute( - dnnl_graph_compiler_tensor *inputs, - dnnl_graph_compiler_tensor *outputs) const { - // TODO: Implement -} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cf686cf6a..c210b46c6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,9 +5,11 @@ endif () include(gtest) -# Static library to be used in tests -add_library(graph_compiler_static STATIC ${GC_LIB_SOURCES}) +# Static graph compiler library to be used in tests +add_mlir_library(graph_compiler_static STATIC ${GC_LIB_SOURCES}) +target_compile_options(obj.graph_compiler_static PUBLIC -fexceptions) target_include_directories(graph_compiler_static PUBLIC ${GC_LIB_INCLUDES}) +target_link_libraries(graph_compiler_static PUBLIC ${GC_LIB_LINKED_LIBS}) add_subdirectory(dnnl) add_subdirectory(mlir) diff --git a/test/dnnl/CMakeLists.txt b/test/dnnl/CMakeLists.txt index d970d3500..612a248c4 100644 --- a/test/dnnl/CMakeLists.txt +++ b/test/dnnl/CMakeLists.txt @@ -1,3 +1,4 @@ + # Copy resources to the build directory file(GLOB_RECURSE TEST_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} resources/*) foreach (TEST_RESOURCE ${TEST_RESOURCES}) @@ -8,16 +9,15 @@ file(GLOB TEST_SOURCES Test*.cpp) foreach (TEST_SOURCE ${TEST_SOURCES}) get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE) add_executable(${TEST_NAME} ${TEST_SOURCE}) - target_include_directories(${TEST_NAME} PUBLIC - ${GC_LIB_INCLUDES} - ${CMAKE_SOURCE_DIR}/src/dnnl - ) - target_link_libraries(${TEST_NAME} graph_compiler_static - gtest - gtest_main - ${GC_LIB_LINKED_LIBS} - ) - add_test(NAME ${TEST_NAME} - COMMAND ${TEST_NAME} - ) + target_include_directories(${TEST_NAME} PRIVATE ${GC_LIB_INCLUDES}) + if (${TEST_NAME} MATCHES "^TestApi.*") + # The API tests are linked with the shared lib + target_link_libraries(${TEST_NAME} PRIVATE graph_compiler) + else () + # The other tests are linked with the static lib and have non-public includes + target_link_libraries(${TEST_NAME} PRIVATE graph_compiler_static) + target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src/dnnl) + endif () + target_link_libraries(${TEST_NAME} PRIVATE gtest gtest_main) + add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) endforeach () diff --git a/test/dnnl/TestDnnlCInterface.cpp b/test/dnnl/TestApiBasic.cpp similarity index 80% rename from test/dnnl/TestDnnlCInterface.cpp rename to test/dnnl/TestApiBasic.cpp index 73c5b8197..3425dbfa4 100644 --- a/test/dnnl/TestDnnlCInterface.cpp +++ b/test/dnnl/TestApiBasic.cpp @@ -22,8 +22,8 @@ #include "gc_version.h" #include "graph/backend/elyzor/include/dnnl_graph_compiler.h" -TEST(TestDnnlCInterface, basicWorkflow) { - auto json = read_str_resource("mpl.json"); +TEST(TestApiBasic, basicWorkflow) { + auto json = read_str_resource("add.json"); const struct dnnl_graph_compiler_context ctx = {.num_threads = 4}; const struct dnnl_graph_compiler *gc; @@ -36,19 +36,28 @@ TEST(TestDnnlCInterface, basicWorkflow) { // Initialize inputs and outputs dnnl_graph_compiler_tensor inputs[2]; dnnl_graph_compiler_tensor outputs[1]; - uint8_t data_buf[160]; - int64_t dims[1] = {10}; - inputs[0] = {.id = 0, .ndims = 1, .dims = dims, .data = data_buf}; - inputs[1] = {.id = 1, .ndims = 1, .dims = dims, .data = &data_buf[40]}; - outputs[0] = {.id = 2, .ndims = 1, .dims = dims, .data = &data_buf[80]}; + float arg1[128]{1.f}; + float arg2[128]; + float arg3[128]; + int64_t dims[1] = {128}; + inputs[0] = {.id = 0, .ndims = 1, .dims = dims, .data = arg1}; + inputs[1] = {.id = 1, .ndims = 1, .dims = dims, .data = arg2}; + outputs[0] = {.id = 2, .ndims = 1, .dims = dims, .data = arg3}; + for (size_t i = 0; i < 128; i++) { + arg2[i] = i; + } ASSERT_EQ(dnnl_graph_compiler_execute(exe, inputs, outputs), dnnl_success); dnnl_graph_compiler_destroy_executable(exe); dnnl_graph_compiler_destroy(gc); + + for (size_t i = 0; i < 128; i++) { + ASSERT_FLOAT_EQ(arg3[i], arg1[i] + arg2[i]); + } } -TEST(TestDnnlCInterface, get_version) { +TEST(TestApiBasic, get_version) { auto v = dnnl_graph_compiler_get_version(); ASSERT_NE(v, nullptr); diff --git a/test/dnnl/TestJsonParser.cpp b/test/dnnl/TestJsonParser.cpp index 99e1c3b8f..9fe67981a 100644 --- a/test/dnnl/TestJsonParser.cpp +++ b/test/dnnl/TestJsonParser.cpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2024 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include "DnnlTestUtils.h" @@ -5,8 +23,10 @@ #include "gc/Transforms/Passes.h" -static mlir::ModuleOp parse(const char *fileName, std::vector &inputIds, - std::vector &outputIds) { +static mlir::ModuleOp parse(const char *fileName, + llvm::SmallVector &inputIds, + llvm::SmallVector &outputIds, + std::unordered_map &strides) { static auto registry = []() { mlir::DialectRegistry registry; mlir::gc::registerGraphCompilerPasses(); @@ -27,7 +47,8 @@ static mlir::ModuleOp parse(const char *fileName, std::vector &inputIds, }(); auto json = read_str_resource(fileName); - mlir::ModuleOp module = JsonParser::parse(context, json, inputIds, outputIds); + mlir::ModuleOp module = + JsonParser::parse(context, json, inputIds, outputIds, strides); if (printModule) { auto &out = llvm::outs(); @@ -48,15 +69,18 @@ static mlir::ModuleOp parse(const char *fileName, std::vector &inputIds, } TEST(TestJsonParser, AddRelu) { - std::vector inputIds; - std::vector outputIds; - mlir::ModuleOp module = parse("add_relu.json", inputIds, outputIds); + llvm::SmallVector inputIds; + llvm::SmallVector outputIds; + std::unordered_map strides; + mlir::ModuleOp module = parse("add_relu.json", inputIds, outputIds, strides); ASSERT_EQ(inputIds.size(), 2); ASSERT_EQ(outputIds.size(), 1); + ASSERT_EQ(strides.size(), 1); ASSERT_EQ(inputIds[0], 0); ASSERT_EQ(inputIds[1], 1); ASSERT_EQ(outputIds[0], 3); + ASSERT_EQ(strides[1], Strides({1, 2, 3, 4})); auto functions = module.getOps(); ASSERT_EQ(std::distance(functions.begin(), functions.end()), 1); @@ -112,12 +136,14 @@ TEST(TestJsonParser, AddRelu) { } TEST(TestJsonParser, Mpl) { - std::vector inputIds; - std::vector outputIds; - mlir::ModuleOp module = parse("mpl.json", inputIds, outputIds); + llvm::SmallVector inputIds; + llvm::SmallVector outputIds; + std::unordered_map strides; + mlir::ModuleOp module = parse("mpl.json", inputIds, outputIds, strides); ASSERT_EQ(inputIds.size(), 5); ASSERT_EQ(outputIds.size(), 1); + ASSERT_EQ(strides.size(), 0); ASSERT_EQ(inputIds[0], 0); ASSERT_EQ(inputIds[1], 1); ASSERT_EQ(inputIds[2], 2); @@ -132,7 +158,7 @@ TEST(TestJsonParser, Mpl) { ASSERT_EQ(funcType.getNumInputs(), 5); ASSERT_EQ(funcType.getNumResults(), 1); - auto checkTensorType = [](mlir::Type type, std::vector dims) { + auto checkTensorType = [](mlir::Type type, llvm::SmallVector dims) { ASSERT_EQ(type.getTypeID(), mlir::RankedTensorType::getTypeID()); auto tensorType = mlir::dyn_cast(type); ASSERT_TRUE(tensorType.getElementType().isBF16()); diff --git a/test/dnnl/resources/add.json b/test/dnnl/resources/add.json new file mode 100644 index 000000000..4df0470b2 --- /dev/null +++ b/test/dnnl/resources/add.json @@ -0,0 +1,43 @@ +{ + "version": "3.5.0", + "engine_kind": "cpu", + "fpmath_mode": "any", + "input_ports": [ + 0, + 1 + ], + "output_ports": [ + 2 + ], + "graph": [ + { + "id": 0, + "kind": "Add", + "inputs": [ + { + "id": 0, + "dtype": "f32", + "shape": [ + 128 + ] + }, + { + "id": 1, + "dtype": "f32", + "shape": [ + 128 + ] + } + ], + "outputs": [ + { + "id": 2, + "dtype": "f32", + "shape": [ + 128 + ] + } + ] + } + ] +} diff --git a/test/dnnl/resources/add_relu.json b/test/dnnl/resources/add_relu.json index 1a68fb8c0..6d0759b42 100644 --- a/test/dnnl/resources/add_relu.json +++ b/test/dnnl/resources/add_relu.json @@ -46,9 +46,9 @@ 28 ], "stride": [ - -9223372036854775808 + 1, 2, 3, 4 ], - "layout_type": "undef", + "layout_type": "strided", "property_type": "undef" } ],