// // Copyright (c) 2023 Apple Inc. All rights reserved. // Provided subject to the LICENSE file in the top level directory. // #include namespace executorch { namespace backends { namespace mps { namespace delegate { MPSGraphTensor* unaryOpTensor( MPSGraphTensor* inputTensor, MPSGraph* mpsGraph, std::function unaryOpFunction) { return unaryOpFunction(inputTensor); } Error MPSGraphBuilder::mpsBitwiseNotOp(NodePtr nodePtr) { auto graphNode = nodePtr->mpsnode_union_as_MPSBitwiseNot(); ET_LOG( Debug, "%s: %d -> %d", __FUNCTION__, graphNode->input1_id(), graphNode->output_id() ); MPSGraphTensor* inputTensor = getMPSGraphTensor(graphNode->input1_id()); MPSDataType mpsInputDataType = [inputTensor dataType]; if (getScalarType(mpsInputDataType) == executorch::aten::ScalarType::Bool) { _idToMPSGraphTensor[graphNode->output_id()] = [_mpsGraph notWithTensor:inputTensor name:nil]; } else { ET_CHECK_OR_RETURN_ERROR( is_macos_13_or_newer(), NotSupported, "mpsBitwiseNotOp supported by MPS on MacOS13.0+/iOS16.1+"); _idToMPSGraphTensor[graphNode->output_id()] = [_mpsGraph bitwiseNOTWithTensor:inputTensor name:nil]; } return Error::Ok; } #define REGISTER_UNARY_OP(aot_name, graph_op) \ Error \ MPSGraphBuilder::mps##aot_name##Op(NodePtr nodePtr) { \ auto graphNode = static_cast(nodePtr->mpsnode_union()); \ ET_LOG( \ Debug, "%s: %d -> %d", \ __FUNCTION__, \ graphNode->input1_id(), \ graphNode->output_id() \ ); \ _idToMPSGraphTensor[graphNode->output_id()] = unaryOpTensor( \ getMPSGraphTensor(graphNode->input1_id()), \ _mpsGraph, \ [&](MPSGraphTensor* inputTensor) -> MPSGraphTensor* { \ return [_mpsGraph graph_op##WithTensor:inputTensor \ name:nil]; \ } \ ); \ return Error::Ok; \ } REGISTER_UNARY_OP(Exp, exponent) REGISTER_UNARY_OP(Exp2, exponentBase2) REGISTER_UNARY_OP(Reciprocal, reciprocal) REGISTER_UNARY_OP(Sqrt, squareRoot) REGISTER_UNARY_OP(Neg, negative) REGISTER_UNARY_OP(Log, logarithm) REGISTER_UNARY_OP(Log10, logarithmBase10) REGISTER_UNARY_OP(Log2, logarithmBase2) REGISTER_UNARY_OP(Erf, erf) REGISTER_UNARY_OP(Floor, floor) REGISTER_UNARY_OP(Ceil, ceil) REGISTER_UNARY_OP(Rsqrt, reverseSquareRoot) REGISTER_UNARY_OP(Sigmoid, sigmoid) REGISTER_UNARY_OP(Sin, sin) REGISTER_UNARY_OP(Sign, sign) REGISTER_UNARY_OP(Cos, cos) REGISTER_UNARY_OP(Tan, tan) REGISTER_UNARY_OP(Abs, absolute) REGISTER_UNARY_OP(Asin, asin) REGISTER_UNARY_OP(Acos, acos) REGISTER_UNARY_OP(Atan, atan) REGISTER_UNARY_OP(Sinh, sinh) REGISTER_UNARY_OP(Cosh, cosh) REGISTER_UNARY_OP(Tanh, tanh) REGISTER_UNARY_OP(Asinh, asinh) REGISTER_UNARY_OP(Acosh, acosh) REGISTER_UNARY_OP(Atanh, atanh) REGISTER_UNARY_OP(Isnan, isNaN) REGISTER_UNARY_OP(Isinf, isInfinite) REGISTER_UNARY_OP(Round, round) REGISTER_UNARY_OP(LogicalNot, not) Error MPSGraphBuilder::mpsNormCdfOp(NodePtr nodePtr) { auto graphNode = static_cast(nodePtr->mpsnode_union()); ET_LOG( Debug, "%s: %d -> %d", __FUNCTION__, graphNode->input1_id(), graphNode->output_id() ); MPSGraphTensor* inputTensor = getMPSGraphTensor(graphNode->input1_id()); auto dataType = [inputTensor dataType]; const float SQRT1_2 = 0.707106781186547524400844362104849039f; MPSGraphTensor *sqrt1_2 = [_mpsGraph constantWithScalar:SQRT1_2 shape:@[@1] dataType:dataType]; MPSGraphTensor *onef = [_mpsGraph constantWithScalar:1.0f shape:@[@1] dataType:dataType]; MPSGraphTensor *halff = [_mpsGraph constantWithScalar:0.5f shape:@[@1] dataType:dataType]; MPSGraphTensor *erfTensor = [_mpsGraph multiplicationWithPrimaryTensor:inputTensor secondaryTensor:sqrt1_2 name:nil]; erfTensor = [_mpsGraph erfWithTensor:erfTensor name:nil]; erfTensor = [_mpsGraph additionWithPrimaryTensor:erfTensor secondaryTensor:onef name:nil]; _idToMPSGraphTensor[graphNode->output_id()] = [_mpsGraph multiplicationWithPrimaryTensor:erfTensor secondaryTensor:halff name:nil]; return Error::Ok; } } // namespace delegate } // namespace mps } // namespace backends } // namespace executorch