Uploaded image for project: 'IMPALA'
  1. IMPALA
  2. IMPALA-4432

Cannot execute IR UDF when single node execution is enabled

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: Impala 2.8.0
    • Fix Version/s: Impala 2.8.0
    • Component/s: Backend
    • Labels:
      None

      Description

      There is a bad interaction between the single-node execution optimisation and IR UDFs. The optimisation overrides the disable_codegen query option, which prevents the UDF from running:

      [tarmstrong-box.ca.cloudera.com:21000] > set disable_codegen=0;
      DISABLE_CODEGEN set to 0
      [tarmstrong-box.ca.cloudera.com:21000] > set EXEC_SINGLE_NODE_ROWS_THRESHOLD=100;
      EXEC_SINGLE_NODE_ROWS_THRESHOLD set to 100
      [tarmstrong-box.ca.cloudera.com:21000] > select twenty_one_args(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21);
      Query: select twenty_one_args(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)
      Query submitted at: 2016-11-04 12:10:49 (Coordinator: http://tarmstrong-box:25000)
      ERROR: Cannot interpret native UDF 'twenty_one_args': number of arguments is more than 20. Codegen is needed. Please set DISABLE_CODEGEN to false.
      

        Issue Links

          Activity

          Hide
          kwho Michael Ho added a comment -

          https://github.com/apache/incubator-impala/commit/b7eeb8bf85ef24b730c9ba2891f5a8075ba9605e

          IMPALA-4432: Handle internal codegen disabling properly

          There are some conditions in which codegen is disabled internally
          even if it's enabled in the query option. For instance, the single
          node optimization or the expression evaluation requests sent from
          the FE to the BE. These internal disabling of codegen are advisory
          as their purposes are to reduce the latency for tables with no or
          very few rows. The internal disabling of codegen doesn't interact
          well with UDFs which cannot be interpreted (e.g. IR UDF) as it
          conflates the 'disable_codegen' query option set by the user.
          As a result, it's hard to differentiate between when codegen is
          disabled explicitly by users and when it is disabled internally.

          This change fixes the problem above by adding an explicit flag in
          TQueryCtx to indicate that codegen is disabled internally. This flag
          is only advisory. For cases in which codegen is needed to function,
          this internal flag is ignored and if codegen is disabled via query
          option, an error is thrown. For this new flag to work with ScalarFnCall,
          codegen needs to happen after ScalarFnCall::Prepare() because it's
          hard to tell if a fragment contains any UDF that cannot be interpreted
          until after ScalarFnCall::Prepare() is called. However, Prepare() needs
          the codegen object to codegen so it needs to be created before Prepare().
          We can either always create the codegen module or defer codegen to a point
          after ScalarFnCall::Prepare(). The former has the downside of introducing
          unnecessary latency for say single-node optimization so the latter is
          implemented. It is needed as part of IMPALA-4192 any way.

          After this change, ScalarFnCall expressions which need to be codegen'd
          are inserted into a vector in RuntimeState in ScalarFnCall::Prepare().
          Later in the codegen phase, these expressions' GetCodegendComputeFn()
          will be called after codegen for operators is done. If any of these
          expressions are already codegen'd indirectly by the operators,
          GetCodegendComputeFn() will be a no-op. This preserves the behavior
          that ScalarFnCall will always be codegen'd even if the fragment
          doesn't contain any codegen enabled operators.

          Change-Id: I0b6a9ed723c64ba21b861608583cc9b6607d3397
          Reviewed-on: http://gerrit.cloudera.org:8080/5105
          Reviewed-by: Michael Ho <kwho@cloudera.com>
          Tested-by: Internal Jenkins

          Show
          kwho Michael Ho added a comment - https://github.com/apache/incubator-impala/commit/b7eeb8bf85ef24b730c9ba2891f5a8075ba9605e IMPALA-4432 : Handle internal codegen disabling properly There are some conditions in which codegen is disabled internally even if it's enabled in the query option. For instance, the single node optimization or the expression evaluation requests sent from the FE to the BE. These internal disabling of codegen are advisory as their purposes are to reduce the latency for tables with no or very few rows. The internal disabling of codegen doesn't interact well with UDFs which cannot be interpreted (e.g. IR UDF) as it conflates the 'disable_codegen' query option set by the user. As a result, it's hard to differentiate between when codegen is disabled explicitly by users and when it is disabled internally. This change fixes the problem above by adding an explicit flag in TQueryCtx to indicate that codegen is disabled internally. This flag is only advisory. For cases in which codegen is needed to function, this internal flag is ignored and if codegen is disabled via query option, an error is thrown. For this new flag to work with ScalarFnCall, codegen needs to happen after ScalarFnCall::Prepare() because it's hard to tell if a fragment contains any UDF that cannot be interpreted until after ScalarFnCall::Prepare() is called. However, Prepare() needs the codegen object to codegen so it needs to be created before Prepare(). We can either always create the codegen module or defer codegen to a point after ScalarFnCall::Prepare(). The former has the downside of introducing unnecessary latency for say single-node optimization so the latter is implemented. It is needed as part of IMPALA-4192 any way. After this change, ScalarFnCall expressions which need to be codegen'd are inserted into a vector in RuntimeState in ScalarFnCall::Prepare(). Later in the codegen phase, these expressions' GetCodegendComputeFn() will be called after codegen for operators is done. If any of these expressions are already codegen'd indirectly by the operators, GetCodegendComputeFn() will be a no-op. This preserves the behavior that ScalarFnCall will always be codegen'd even if the fragment doesn't contain any codegen enabled operators. Change-Id: I0b6a9ed723c64ba21b861608583cc9b6607d3397 Reviewed-on: http://gerrit.cloudera.org:8080/5105 Reviewed-by: Michael Ho <kwho@cloudera.com> Tested-by: Internal Jenkins
          Hide
          jrussell John Russell added a comment -

          Added new "known issue" item in this gerrit review: https://gerrit.cloudera.org/#/c/5809/

          Show
          jrussell John Russell added a comment - Added new "known issue" item in this gerrit review: https://gerrit.cloudera.org/#/c/5809/

            People

            • Assignee:
              kwho Michael Ho
              Reporter:
              tarmstrong Tim Armstrong
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development