-
Notifications
You must be signed in to change notification settings - Fork 651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FIX-#4564: Workaround import issues in Ray: auto-import pandas on python start if env var is set #4603
FIX-#4564: Workaround import issues in Ray: auto-import pandas on python start if env var is set #4603
Changes from 11 commits
e2fe3c5
cddfba1
a8d568d
848d8b2
843dbbb
965c5b9
2eb728f
158f0f3
2373716
23bdcec
e426ce0
a24c723
0ac7c82
995febd
49029e2
2a8b4f7
887a5f4
01682b0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import os; os.environ.get("__MODIN_AUTOIMPORT_PANDAS__", None) and __import__("pandas") |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ | |
NPartitions, | ||
ValueSource, | ||
) | ||
from modin.error_message import ErrorMessage | ||
|
||
ObjectIDType = ray.ObjectRef | ||
if version.parse(ray.__version__) >= version.parse("1.2.0"): | ||
|
@@ -40,60 +41,6 @@ | |
ObjectIDType = (ray.ObjectRef, ClientObjectRef) | ||
|
||
|
||
def _move_stdlib_ahead_of_site_packages(*args): | ||
""" | ||
Ensure packages from stdlib have higher import priority than from site-packages. | ||
|
||
Parameters | ||
---------- | ||
*args : tuple | ||
Ignored, added for compatibility with Ray. | ||
|
||
Notes | ||
----- | ||
This function is expected to be run on all workers including the driver. | ||
This is a hack solution to fix GH-#647, GH-#746. | ||
""" | ||
site_packages_path = None | ||
site_packages_path_index = -1 | ||
for i, path in enumerate(sys.path): | ||
if sys.exec_prefix in path and path.endswith("site-packages"): | ||
site_packages_path = path | ||
site_packages_path_index = i | ||
# break on first found | ||
break | ||
|
||
if site_packages_path is not None: | ||
# stdlib packages layout as follows: | ||
# - python3.x | ||
# - typing.py | ||
# - site-packages/ | ||
# - pandas | ||
# So extracting the dirname of the site_packages can point us | ||
# to the directory containing standard libraries. | ||
sys.path.insert(site_packages_path_index, os.path.dirname(site_packages_path)) | ||
|
||
|
||
def _import_pandas(*args): | ||
""" | ||
Import pandas to make sure all its machinery is ready. | ||
|
||
This prevents a race condition between two threads deserializing functions | ||
and trying to import pandas at the same time. | ||
|
||
Parameters | ||
---------- | ||
*args : tuple | ||
Ignored, added for compatibility with Ray. | ||
|
||
Notes | ||
----- | ||
This function is expected to be run on all workers before any | ||
serialization or deserialization starts. | ||
""" | ||
import pandas # noqa F401 | ||
|
||
|
||
def initialize_ray( | ||
override_is_cluster=False, | ||
override_redis_address: str = None, | ||
|
@@ -117,6 +64,7 @@ def initialize_ray( | |
What password to use when connecting to Redis. | ||
If not specified, ``modin.config.RayRedisPassword`` is used. | ||
""" | ||
extra_init_kw = {"runtime_env": {"env_vars": {"__MODIN_AUTOIMPORT_PANDAS__": "1"}}} | ||
if not ray.is_initialized() or override_is_cluster: | ||
cluster = override_is_cluster or IsRayCluster.get() | ||
redis_address = override_redis_address or RayRedisAddress.get() | ||
|
@@ -138,17 +86,16 @@ def initialize_ray( | |
include_dashboard=False, | ||
ignore_reinit_error=True, | ||
_redis_password=redis_password, | ||
**extra_init_kw, | ||
) | ||
else: | ||
from modin.error_message import ErrorMessage | ||
|
||
# This string is intentionally formatted this way. We want it indented in | ||
# the warning message. | ||
ErrorMessage.not_initialized( | ||
"Ray", | ||
""" | ||
f""" | ||
import ray | ||
ray.init() | ||
ray.init({', '.join([f'{k}={v}' for k,v in extra_init_kw.items()])}) | ||
YarShev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""", | ||
) | ||
object_store_memory = Memory.get() | ||
|
@@ -206,6 +153,7 @@ def initialize_ray( | |
"object_store_memory": object_store_memory, | ||
"_redis_password": redis_password, | ||
"_memory": object_store_memory, | ||
**extra_init_kw, | ||
} | ||
ray.init(**ray_init_kwargs) | ||
|
||
|
@@ -219,11 +167,15 @@ def initialize_ray( | |
if not GPU_MANAGERS: | ||
for i in range(GpuCount.get()): | ||
GPU_MANAGERS.append(GPUManager.remote(i)) | ||
_move_stdlib_ahead_of_site_packages() | ||
ray.worker.global_worker.run_function_on_all_workers( | ||
_move_stdlib_ahead_of_site_packages | ||
) | ||
ray.worker.global_worker.run_function_on_all_workers(_import_pandas) | ||
else: # ray is already initialized, check runtime env config | ||
env_vars = ray.get_runtime_context().runtime_env.get("env_vars", {}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This only checks that the head nodes env vars are set correctly, right? Don't we need to set the environment variable on all of the workers/nodes, and if so, shouldn't we be checking that the env vars are set correctly on all of the workers? We could probably do that using the ray function that runs on all workers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, |
||
for varname, varvalue in extra_init_kw["runtime_env"]["env_vars"].items(): | ||
if str(env_vars.get(varname, "")) != str(varvalue): | ||
ErrorMessage.single_warning( | ||
"If initialising Ray yourself, please ensure its runtime env " | ||
vnlitvinov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
+ f"sets environment variable {varname} to {varvalue}" | ||
vnlitvinov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
|
||
num_cpus = int(ray.cluster_resources()["CPU"]) | ||
num_gpus = int(ray.cluster_resources().get("GPU", 0)) | ||
if StorageFormat.get() == "Cudf": | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you check this case? I can't find that extra parameters could be provided in case of existing cluster https://github.com/ray-project/ray/blob/master/python/ray/_private/worker.py#L1400-L1412
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hadn't, but apparently extra ones would just get ignored, and, if in the future we'll add more arguments than
runtime_env
it would be useful.As for the runtime environment being different, there is a code later on checking the variables. It should give a warning to the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate why it would be useful?
What the code do you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This creates one central place to add more arguments to
ray.init()
instead of copy-pasting them in several different places.modin/modin/core/execution/ray/common/utils.py
Lines 170 to 177 in e426ce0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't hit this branch in case of cluster init.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh?.. we either call
ray.init()
or hit thiselse:
branch.We hit
ray.init()
at line 84 (underif cluster:
) or at line 158 (inelse
branch of thatif cluster
).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just wondering if we should check the runtime environment after ray.init() in case Modin itself initializes Ray? Because of this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point!