在apache spark中表现UDF

时间:2016-08-17 08:19:08

标签: apache-spark apache-spark-sql

我正在尝试进行需要自定义功能的高性能计算。

作为第一阶段,我试图分析使用UDF的效果,我得到了奇怪的结果。

我创建了一个简单的测试(在https://databricks-prod-cloudfront.cloud.databricks.com/public/4027ec902e239c93eaaa8714f173bcfc/6100413009427980/1838590056414286/3882373005101896/latest.html

基本上我使用带有50M记录的range选项创建一个数据帧并缓存它。

然后我做一个过滤器来找到小于10的那些并计算它们。一旦做了列< 10,一次通过UDF。

我每次动作10次以获得好时间估计。

我发现这两种方法大约在同一时间:约4秒。

我也在我拥有的一个内部集群中尝试过它(8个节点,使用yarn,每个节点有~40GB内存和大量内核)。第一个选项的结果是1秒,第二个选项的结果是8秒。

首先,我不明白在databricks集群中我是如何获得相同的性能的。 UDF不应该慢得多吗?毕竟,没有codegen所以我应该看到一个慢得多的过程。

其次我不明白这两个问题之间的巨大差异:在一个我几乎相同的时间和另一个x8差异。

最后,我试图弄清楚如何在本地编写自定义函数(即spark的方式)。我试着看一下spark的代码,然后出现了类似的东西:

import org.apache.spark.sql.catalyst.InternalRow 
import org.apache.spark.sql.catalyst.analysis.TypeCheckResult 
import org.apache.spark.sql.catalyst.expressions.codegen.{CodegenContext, ExprCode} 
import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan 
import org.apache.spark.sql.catalyst.util.TypeUtils 
import org.apache.spark.sql.types._ 
import org.apache.spark.util.Utils 
import org.apache.spark.sql.catalyst.expressions._

case class genf(child: Expression) extends UnaryExpression with Predicate with ImplicitCastInputTypes {

  override def inputTypes: Seq[AbstractDataType] = Seq(IntegerType)

  override def toString: String = s"$child < 10"

  override def eval(input: InternalRow): Any = { 
    val value = child.eval(input) 
    if (value == null) 
    { 
      false
    } else {
      child.dataType match {
        case IntegerType => value.asInstanceOf[Int] < 10 
      } 
    } 
  }

  override def doGenCode(ctx: CodegenContext, ev: ExprCode): ExprCode = {
   defineCodeGen(ctx, ev, c => s"($c) < 10") 
  } 
}

然而,这不起作用,因为它只能在sql包中起作用(例如,AbstractDataType是私有的)。

这个代码是否在正确的方向?我怎么能让它发挥作用?

感谢。

0 个答案:

没有答案