如何在AWS EMR上设置PYTHONHASHSEED

时间:2016-11-18 12:56:32

标签: python-3.x amazon-web-services apache-spark pyspark amazon-emr

有没有办法在EMR集群的所有节点上设置环境变量?

尝试在Python3 PySpark中使用reduceByKey()时收到错误,并收到有关散列种子的错误。我可以看到这是一个已知的错误,并且环境变量PYTHONHASHSEED需要在集群的所有节点上设置为相同的值,但我没有任何运气。

我尝试通过群集配置向spark-env添加变量:

[
  {
    "Classification": "spark-env",

      "Configurations": [
      {
         "Classification": "export",
         "Properties": {
          "PYSPARK_PYTHON": "/usr/bin/python3",
          "PYTHONHASHSEED": "123"
       }
     }
   ]
 },
 {
   "Classification": "spark",
   "Properties": {
     "maximizeResourceAllocation": "true"
    }
  }
]

但这不起作用。我还尝试添加一个引导脚本:

#!/bin/bash
export PYTHONHASHSEED=123

但这似乎也没有诀窍。

4 个答案:

答案 0 :(得分:7)

我认为/usr/bin/python3没有获取您在PYTHONHASHSEED范围下的群集配置中定义的环境变量spark-env

您应该使用python34代替/usr/bin/python3并将配置设置如下:

[
   {
      "classification":"spark-defaults",
      "properties":{
         // [...]
      }
   },
   {
      "configurations":[
         {
            "classification":"export",
            "properties":{
               "PYSPARK_PYTHON":"python34",
               "PYTHONHASHSEED":"123"
            }
         }
      ],
      "classification":"spark-env",
      "properties":{
        // [...]
      }
   }
]

现在,让我们来测试一下。我定义了一个bash脚本调用python s:

#!/bin/bash

echo "using python34"
for i in `seq 1 10`;
  do
    python -c "print(hash('foo'))";
  done
echo "----------------------"
echo "using /usr/bin/python3"
for i in `seq 1 10`;
  do
    /usr/bin/python3 -c "print(hash('foo'))";
  done

判决结果:

[hadoop@ip-10-0-2-182 ~]$ bash test.sh
using python34
-4177197833195190597
-4177197833195190597
-4177197833195190597
-4177197833195190597
-4177197833195190597
-4177197833195190597
-4177197833195190597
-4177197833195190597
-4177197833195190597
-4177197833195190597
----------------------
using /usr/bin/python3
8867846273747294950
-7610044127871105351
6756286456855631480
-4541503224938367706
7326699722121877093
3336202789104553110
3462714165845110404
-5390125375246848302
-7753272571662122146
8018968546238984314

PS1:我正在使用AMI版本emr-4.8.2

PS2:摘自this answer

编辑:我使用pyspark测试了以下内容。

16/11/22 07:16:56 INFO EventLoggingListener: Logging events to hdfs:///var/log/spark/apps/application_1479798580078_0001
16/11/22 07:16:56 INFO YarnClientSchedulerBackend: SchedulerBackend is ready for scheduling beginning after reached minRegisteredResourcesRatio: 0.8
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 1.6.2
      /_/

Using Python version 3.4.3 (default, Sep  1 2016 23:33:38)
SparkContext available as sc, HiveContext available as sqlContext.
>>> print(hash('foo'))
-2457967226571033580
>>> print(hash('foo'))
-2457967226571033580
>>> print(hash('foo'))
-2457967226571033580
>>> print(hash('foo'))
-2457967226571033580
>>> print(hash('foo'))
-2457967226571033580

还创建了一个简单的应用程序(simple_app.py):

from pyspark import SparkContext

sc = SparkContext(appName = "simple-app")

numbers = [hash('foo') for i in range(10)]

print(numbers)

这似乎也很完美:

[hadoop@ip-*** ~]$ spark-submit --master yarn simple_app.py 

输出(截断):

[...]
16/11/22 07:28:42 INFO YarnClientSchedulerBackend: SchedulerBackend is ready for scheduling beginning after reached minRegisteredResourcesRatio: 0.8
[-5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594] // THE RELEVANT LINE IS HERE.
16/11/22 07:28:42 INFO SparkContext: Invoking stop() from shutdown hook
[...]

正如您所看到的,它每次都会返回相同的哈希值。

编辑2:从评论中看来,您似乎正在尝试计算执行者而不是驱动程序的哈希值,因此您需要在您的内部设置spark.executorEnv.PYTHONHASHSEED spark应用程序配置,因此它可以在执行程序上传播(这是一种方法)。

  

注意:为执行程序设置环境变量与YARN客户端相同,请使用spark.executorEnv.[EnvironmentVariableName].

因此下面的简约示例包含simple_app.py

from pyspark import SparkContext, SparkConf

conf = SparkConf().set("spark.executorEnv.PYTHONHASHSEED","123")
sc = SparkContext(appName="simple-app", conf=conf)

numbers = sc.parallelize(['foo']*10).map(lambda x: hash(x)).collect()

print(numbers)

现在让我们再试一次。这是截断的输出:

16/11/22 14:14:34 INFO DAGScheduler: Job 0 finished: collect at /home/hadoop/simple_app.py:6, took 14.251514 s
[-5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594, -5869373620241885594]
16/11/22 14:14:34 INFO SparkContext: Invoking stop() from shutdown hook

我认为这涵盖了所有。

答案 1 :(得分:2)

来自火花docs

  

注意:在群集模式下在YARN上运行Spark时,需要使用conf / spark-defaults.conf文件中的spark.yarn.appMasterEnv。[EnvironmentVariableName]属性设置环境变量。 spark-env.sh中设置的环境变量不会以群集模式反映在YARN Application Master进程中。有关详细信息,请参阅与YARN相关的Spark属性。

列出了here属性,所以我想你想要这个:

  

将EnvironmentVariableName指定的环境变量添加到在YARN上启动的Application Master进程。

spark.yarn.appMasterEnv.PYTHONHASHSEED="XXXX"

配置spark-defaults.conf的EMR文档是here

[
    {
      "Classification": "spark-defaults",
      "Properties": {
        "spark.yarn.appMasterEnv.PYTHONHASHSEED: "XXX"
      }
    }
]

答案 2 :(得分:2)

刚遇到同样的问题,添加以下配置解决了它:

# Some settings...
Configurations=[
        {
            "Classification": "spark-env",
            "Properties": {},
            "Configurations": [
                {
                    "Classification": "export",
                    "Properties": {
                        "PYSPARK_PYTHON": "python34"
                    },
                    "Configurations": []
                }
            ]
        },
        {
            "Classification": "hadoop-env",
            "Properties": {},
            "Configurations": [
                {
                    "Classification": "export",
                    "Properties": {
                        "PYTHONHASHSEED": "0"
                    },
                    "Configurations": []
                }
            ]
        }
        ],
# Some more settings...

注意:我们不使用yarn作为集群管理器,因为集群只运行Hadoop和Spark。

编辑:根据Tim B评论,这似乎也适用于作为集群管理器安装的纱线。

答案 3 :(得分:1)

您可以通过引导程序脚本执行此操作,但您需要执行以下操作:

echo "PYTHONHASHSEED=XXXX" >> /home/hadoop/.bashrc

(或可能是.profile

因此,当它们被启动时,它会被火花过程所吸引。

您的配置看起来很合理,可能值得在hadoop-env部分进行设置吗?