From 8bb5c8c01794bd53a0b7840ec66b7a009ee48313 Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Wed, 13 Dec 2023 17:39:37 -0500 Subject: [PATCH] Take a crack at the hyb prim case. --- .../hybridize/core/analysis/Function.java | 24 ++++++-- .../core/analysis/PreconditionFailure.java | 7 ++- .../core/analysis/PreconditionSuccess.java | 3 +- .../HybridizeFunction/testRetracing4/in/A.py | 16 ++++++ .../testRetracing4/in/requirements.txt | 1 + .../HybridizeFunction/testRetracing5/in/A.py | 15 +++++ .../testRetracing5/in/requirements.txt | 1 + .../HybridizeFunctionRefactoringTest.java | 55 ++++++++++++++++++- 8 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing4/in/A.py create mode 100644 edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing4/in/requirements.txt create mode 100644 edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing5/in/A.py create mode 100644 edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing5/in/requirements.txt diff --git a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Function.java b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Function.java index 0cdf72d5c..928ed23ce 100644 --- a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Function.java +++ b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Function.java @@ -1,8 +1,10 @@ package edu.cuny.hunter.hybridize.core.analysis; import static edu.cuny.hunter.hybridize.core.analysis.PreconditionFailure.HAS_PRIMITIVE_PARAMETERS; +import static edu.cuny.hunter.hybridize.core.analysis.PreconditionFailure.HAS_PYTHON_SIDE_EFFECTS; import static edu.cuny.hunter.hybridize.core.analysis.PreconditionSuccess.P1; import static edu.cuny.hunter.hybridize.core.analysis.PreconditionSuccess.P2; +import static edu.cuny.hunter.hybridize.core.analysis.PreconditionSuccess.P3; import static edu.cuny.hunter.hybridize.core.analysis.Refactoring.CONVERT_EAGER_FUNCTION_TO_HYBRID; import static edu.cuny.hunter.hybridize.core.analysis.Refactoring.OPTIMIZE_HYBRID_FUNCTION; import static edu.cuny.hunter.hybridize.core.analysis.Transformation.CONVERT_TO_EAGER; @@ -1220,12 +1222,22 @@ public void check() { this.addFailure(PreconditionFailure.HAS_PYTHON_SIDE_EFFECTS, "De-hybridizing a function with Python side-effects may alter semantics."); } else if (this.getLikelyHasTensorParameter() != null) { // it has a tensor parameter. - this.addFailure(PreconditionFailure.HAS_TENSOR_PARAMETERS, - "Functions with tensor parameters may benefit from hybreidization."); - - if (this.getHasPythonSideEffects() != null && this.getHasPythonSideEffects()) { - this.addFailure(PreconditionFailure.HAS_PYTHON_SIDE_EFFECTS, - "De-hybridizing a function with Python side-effects may alter semantics."); + // if it has primitive parameters. + if (this.getLikelyHasPrimitiveParameters() != null && this.getLikelyHasPrimitiveParameters()) { + // if it does not have side-effects. + if (this.getHasPythonSideEffects() != null && !this.getHasPythonSideEffects()) { + this.addTransformation(CONVERT_TO_EAGER); + this.setPassingPrecondition(P3); + } else if (this.getHasPythonSideEffects() != null) // it has side-effects. + this.addFailure(HAS_PYTHON_SIDE_EFFECTS, "De-hybridizing a function with Python side-effects may alter semantics."); + } else if (this.getLikelyHasPrimitiveParameters() != null) { // no primitive parameters. + this.addFailure(PreconditionFailure.HAS_NO_PRIMITIVE_PARAMETERS, + "Functions with no Python literal arguments may benefit from hybridization."); + + if (this.getHasPythonSideEffects() != null && this.getHasPythonSideEffects()) { + this.addFailure(PreconditionFailure.HAS_PYTHON_SIDE_EFFECTS, + "De-hybridizing a function with Python side-effects may alter semantics."); + } } // Here, we have a hybrid function with a tensor parameter. diff --git a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/PreconditionFailure.java b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/PreconditionFailure.java index a32c0a546..1bb21d625 100644 --- a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/PreconditionFailure.java +++ b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/PreconditionFailure.java @@ -36,7 +36,12 @@ public enum PreconditionFailure { */ UNDETERMINABLE_PRIMITIVE_PARAMETER(11), - HAS_PRIMITIVE_PARAMETERS(12); + HAS_PRIMITIVE_PARAMETERS(12), + + /** + * P3 failure. + */ + HAS_NO_PRIMITIVE_PARAMETERS(13); static { // check that the codes are unique. diff --git a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/PreconditionSuccess.java b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/PreconditionSuccess.java index 28c236756..4ef6bc50e 100644 --- a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/PreconditionSuccess.java +++ b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/PreconditionSuccess.java @@ -1,8 +1,7 @@ package edu.cuny.hunter.hybridize.core.analysis; public enum PreconditionSuccess { - P1, P2, - // P3, + P1, P2, P3, // P4, // P5 } diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing4/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing4/in/A.py new file mode 100644 index 000000000..e905abe71 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing4/in/A.py @@ -0,0 +1,16 @@ +# From https://www.tensorflow.org/versions/r2.9/api_docs/python/tf/function#retracing. + +import tensorflow as tf + + +@tf.function +def f(x): + print(x) + return tf.abs(x) + + +print(f(1)) +print(f(2)) # Slow - compiles new graph + +print(f(tf.constant(1))) +print(f(tf.constant(2))) # Fast - reuses f1 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing4/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing4/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing4/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing5/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing5/in/A.py new file mode 100644 index 000000000..0710bf610 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing5/in/A.py @@ -0,0 +1,15 @@ +# From https://www.tensorflow.org/versions/r2.9/api_docs/python/tf/function#retracing. + +import tensorflow as tf + + +@tf.function +def f(x): + return tf.abs(x) + + +# print(f(1)) +# print(f(2)) # Slow - compiles new graph + +print(f(tf.constant(1))) +print(f(tf.constant(2))) # Fast - reuses f1 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing5/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing5/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testRetracing5/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/test cases/edu/cuny/hunter/hybridize/tests/HybridizeFunctionRefactoringTest.java b/edu.cuny.hunter.hybridize.tests/test cases/edu/cuny/hunter/hybridize/tests/HybridizeFunctionRefactoringTest.java index 4f513066b..3432aeb74 100644 --- a/edu.cuny.hunter.hybridize.tests/test cases/edu/cuny/hunter/hybridize/tests/HybridizeFunctionRefactoringTest.java +++ b/edu.cuny.hunter.hybridize.tests/test cases/edu/cuny/hunter/hybridize/tests/HybridizeFunctionRefactoringTest.java @@ -1,6 +1,7 @@ package edu.cuny.hunter.hybridize.tests; import static edu.cuny.hunter.hybridize.core.analysis.PreconditionFailure.CANT_APPROXIMATE_RECURSION; +import static edu.cuny.hunter.hybridize.core.analysis.PreconditionFailure.HAS_NO_PRIMITIVE_PARAMETERS; import static edu.cuny.hunter.hybridize.core.analysis.PreconditionFailure.HAS_NO_TENSOR_PARAMETERS; import static edu.cuny.hunter.hybridize.core.analysis.PreconditionFailure.HAS_PRIMITIVE_PARAMETERS; import static edu.cuny.hunter.hybridize.core.analysis.PreconditionFailure.HAS_PYTHON_SIDE_EFFECTS; @@ -10,10 +11,12 @@ import static edu.cuny.hunter.hybridize.core.analysis.PreconditionFailure.UNDETERMINABLE_TENSOR_PARAMETER; import static edu.cuny.hunter.hybridize.core.analysis.PreconditionSuccess.P1; import static edu.cuny.hunter.hybridize.core.analysis.PreconditionSuccess.P2; +import static edu.cuny.hunter.hybridize.core.analysis.PreconditionSuccess.P3; import static edu.cuny.hunter.hybridize.core.analysis.Refactoring.CONVERT_EAGER_FUNCTION_TO_HYBRID; import static edu.cuny.hunter.hybridize.core.analysis.Refactoring.OPTIMIZE_HYBRID_FUNCTION; import static edu.cuny.hunter.hybridize.core.analysis.Transformation.CONVERT_TO_EAGER; import static edu.cuny.hunter.hybridize.core.analysis.Transformation.CONVERT_TO_HYBRID; +import static java.util.Collections.singleton; import static org.eclipse.core.runtime.Platform.getLog; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -5987,12 +5990,58 @@ public void testRetracing2() throws Exception { @Test public void testRetracing3() throws Exception { Function f = getFunction("f"); - assertTrue(f.getLikelyHasTensorParameter()); - assertTrue(f.getLikelyHasPrimitiveParameters()); - assertTrue(f.getIsHybrid()); + + assertTrue(f.getIsHybrid()); // hyb + assertTrue(f.getLikelyHasTensorParameter()); // T + assertTrue(f.getLikelyHasPrimitiveParameters()); // T + assertFalse(f.getHasPythonSideEffects()); // F + + assertEquals(OPTIMIZE_HYBRID_FUNCTION, f.getRefactoring()); + assertNotNull(f.getPassingPrecondition()); + assertEquals(P3, f.getPassingPrecondition()); + assertFalse(f.getStatus().hasError()); + assertNull(f.getEntryMatchingFailure(HAS_PRIMITIVE_PARAMETERS)); + assertFalse(f.getTransformations().isEmpty()); + assertEquals(singleton(CONVERT_TO_EAGER), f.getTransformations()); + } + + /** + * Test https://www.tensorflow.org/versions/r2.9/api_docs/python/tf/function#retracing, + */ + @Test + public void testRetracing4() throws Exception { + Function f = getFunction("f"); + + assertTrue(f.getIsHybrid()); // hyb + assertTrue(f.getLikelyHasTensorParameter()); // T + assertTrue(f.getLikelyHasPrimitiveParameters()); // T + assertTrue(f.getHasPythonSideEffects()); // T + assertEquals(OPTIMIZE_HYBRID_FUNCTION, f.getRefactoring()); assertNull(f.getPassingPrecondition()); + assertTrue(f.getStatus().hasError()); assertNull(f.getEntryMatchingFailure(HAS_PRIMITIVE_PARAMETERS)); + assertNotNull(f.getEntryMatchingFailure(HAS_PYTHON_SIDE_EFFECTS)); + assertTrue(f.getTransformations().isEmpty()); + } + + /** + * Test https://www.tensorflow.org/versions/r2.9/api_docs/python/tf/function#retracing, + */ + @Test + public void testRetracing5() throws Exception { + Function f = getFunction("f"); + + assertTrue(f.getIsHybrid()); // hyb + assertTrue(f.getLikelyHasTensorParameter()); // T + assertFalse(f.getLikelyHasPrimitiveParameters()); // F + assertFalse(f.getHasPythonSideEffects()); // F + + assertEquals(OPTIMIZE_HYBRID_FUNCTION, f.getRefactoring()); + assertNull(f.getPassingPrecondition()); + assertTrue(f.getStatus().hasError()); + assertNotNull(f.getEntryMatchingFailure(HAS_NO_PRIMITIVE_PARAMETERS)); + assertNull(f.getEntryMatchingFailure(HAS_TENSOR_PARAMETERS)); assertTrue(f.getTransformations().isEmpty()); } }