Python 通过实施常见的fizzbuzz访谈编码问题,对Pyspark与Pandas进行基准测试

Python 通过实施常见的fizzbuzz访谈编码问题,对Pyspark与Pandas进行基准测试,python,pandas,apache-spark,pyspark,Python,Pandas,Apache Spark,Pyspark,我已经阅读了关于为什么pyspark在本地机器上的性能可能比纯python差的各种堆栈溢出问题的答案。这些答复包括以下建议: 并行处理的好处只有在拥有大量内核时才会显现出来 Pyspark的好处只有在数据集大小非常大时才会显现出来 关于第1点,引用Ahmdahl定律的堆栈溢出答案()表明,如果问题是高度可并行的,那么如果我选择了正确的问题,我的8核计算机应该能够提供显著的延迟改进。 一个应该高度并行化的问题是常见的FizzBuzz编码问题。也就是说,对于一个整数序列(1,2,3,…,等等),对每

我已经阅读了关于为什么pyspark在本地机器上的性能可能比纯python差的各种堆栈溢出问题的答案。这些答复包括以下建议:

  • 并行处理的好处只有在拥有大量内核时才会显现出来
  • Pyspark的好处只有在数据集大小非常大时才会显现出来
  • 关于第1点,引用Ahmdahl定律的堆栈溢出答案()表明,如果问题是高度可并行的,那么如果我选择了正确的问题,我的8核计算机应该能够提供显著的延迟改进。 一个应该高度并行化的问题是常见的FizzBuzz编码问题。也就是说,对于一个整数序列(1,2,3,…,等等),对每个整数进行变换,如果该数字可被3整除,则将其替换为“fizz”;如果数字可被5整除,则用“嗡嗡声”替换;如果数字可以被3和5整除,则用“嘶嘶嗡嗡”替换。这应该是一个高度并行化的任务

    我已经使用python pandas、Pyspark dataframes和Pyspark RDD实现了这个Fizzbuzz函数,并改变了数字输入列表的大小,以比较每个实现对性能的影响

    以下是数字列表长度为1亿的每个实现的代码:

    • Python实现(1亿个数字):

       import pandas as pd
       def fizzbuzz(num):
           return "fizzbuzz" if (num % 3 ==0) & (num % 5 == 0) else "fizz" if num % 3 == 0 else "buzz" if num % 5 ==0 else num
      
       pd.DataFrame(range(1,100000001))[0].apply(lambda x: fizzbuzz(x))
      
       def fizzbuzzSpark(num):
           return "fizzbuzz" if (int(num) % 3 ==0) & (int(num) % 5 == 0) else "fizz" if int(num) % 3 == 0 else "buzz" if int(num) % 5 ==0 else str(num)
       fizzbuzz_UDF = functions.udf(fizzbuzzSpark, StringType())
       df_spark = spark.createDataFrame(range(1,1000001), StringType())
       df_spark = df_spark.withColumn('answer',fizzbuzz_UDF(col("value")))
      
    • Pyspark RDD实施(1亿个)

    • Pyspark数据帧UDF实现(100万个):

       import pandas as pd
       def fizzbuzz(num):
           return "fizzbuzz" if (num % 3 ==0) & (num % 5 == 0) else "fizz" if num % 3 == 0 else "buzz" if num % 5 ==0 else num
      
       pd.DataFrame(range(1,100000001))[0].apply(lambda x: fizzbuzz(x))
      
       def fizzbuzzSpark(num):
           return "fizzbuzz" if (int(num) % 3 ==0) & (int(num) % 5 == 0) else "fizz" if int(num) % 3 == 0 else "buzz" if int(num) % 5 ==0 else str(num)
       fizzbuzz_UDF = functions.udf(fizzbuzzSpark, StringType())
       df_spark = spark.createDataFrame(range(1,1000001), StringType())
       df_spark = df_spark.withColumn('answer',fizzbuzz_UDF(col("value")))
      
    下图显示了执行时间如何随着数据集大小的变化而变化(即随着数字列表变大)。 [链接到执行大小与数据集大小的关系图][1] [1]: https://i.stack.imgur.com/9zVoA.png

        Length of Numbers list  1K            10K       100k        1m        10m        100m
    
        Pandas                  0.43 msec     2.3 msec  24.3 msec   246 msec  2.59 sec   24.8 sec
        Pyspark RDD             31 msec       36 msec   70 msec     292 msec  2.56 sec   43.3 sec
        PySpark Dataframe       13 msec       20 msec   91.2 msec   820 msec  8.12 sec   87 sec
    
    看起来熊猫的表现一直优于Pypark。此外,数据集大小之间的关系似乎已收敛到如图所示的日志(执行时间)/日志(数据集大小)的恒定比率


    这个分析正确吗?随着数据集变得越来越大,PySpark的性能是否有可能发生重大变化?如果在一个更大的集群上运行,我会期待截然不同的结果吗?

    只是不要使用udf。它们在pyspark数据帧上的表现非常糟糕。RDD也是如此,因为您也在调用Python代码。尝试使用pure spark sql代码,应该很快谢谢@mck当你说“pure spark”时你建议用Scala编码吗?不,使用spark sql(例如case when)