故障排除#
我们希望您使用Modin的体验是无错误的,但Modin有一些可能需要故障排除的特性。如果您仍然遇到问题,请在我们的Slack社区的#support频道上发帖,或者在Github上打开一个issue。
常见问题#
这是使用Modin时最常遇到的问题列表。其中一些问题是有意为之,而其他一些是已知的正在积极修复的错误。
执行期间的警告:defaulting to pandas#
请注意,虽然Modin涵盖了pandas API的大部分内容,但并非所有功能都已实现。对于尚未实现的方法,例如asfreq,您可能会看到以下内容:
UserWarning: `DataFrame.asfreq` defaulting to pandas implementation.
要了解哪些函数会导致此警告,我们编制了一份当前支持的方法列表。当您看到此警告时,Modin 默认会通过将 Modin 数据框转换为 pandas 来执行操作。一旦在 pandas 中完成操作,它将被转换回 Modin 数据框。由于涉及通信,这些操作将具有较高的开销,并且比 pandas 花费更长的时间。当这种情况发生时,将向用户发出警告,告知他们此操作将比平常花费更长的时间。您可以在此了解更多。
如果您希望请求实现特定的方法,请随时打开一个 issue。在打开问题之前,请确保没有其他人已经 请求了该功能。
挂起在 import modin.pandas as pd#
当Ray启动失败时可能会发生这种情况。它会不断重试,但通常重启笔记本或解释器会更快。一般来说,这不应该发生。最常见的情况是在快速连续启动多个笔记本或解释器时遇到此问题。
解决方案
重新启动您的解释器或笔记本内核。
避免此错误
避免快速连续启动多个Modin笔记本或解释器。在启动下一个之前等待2-3秒。
使用read_csv导入异构数据#
由于Modin的read_csv是并行导入数据的,因此跨分区的数据可能是异构类型的(当列包含异构数据时,即同一列中的值属于不同类型,可能会发生这种情况)。下面展示了一个如何处理这种情况的示例。
import os
import pandas
import modin.pandas as pd
from modin.config import NPartitions
NPartitions.put(2)
test_filename = "test.csv"
# data with heterogeneous values in the first column
data = """one,2
3,4
5,6
7,8
9.0,10
"""
kwargs = {
# names of the columns to set, if `names` parameter is set,
# header inffering from the first data row/rows will be disabled
"names": ["col1", "col2"],
# explicit setting of data type of column/columns with heterogeneous
# data will force partitions to read data with correct dtype
# "dtype": {"col1": str},
}
try :
with open(test_filename, "w") as f:
f.write(data)
pandas_df = pandas.read_csv(test_filename, **kwargs)
pd_df = pd.read_csv(test_filename, **kwargs)
print(pandas_df)
print(pd_df)
finally:
os.remove(test_filename)
Output:
pandas_df:
col1 col2
0 one 2
1 3 4
2 5 6
3 7 8
4 9.0 10
pd_df:
col1 col2
0 one 2
1 3 4
2 5 6
3 7.0 8
4 9.0 10
在这种情况下,由pandas读取的DataFrame的col1仅包含str数据,因为第一个值(“one”)被推断为str类型,这迫使pandas将列中的其余值作为字符串处理。第一个Modin分区(前三行)像pandas一样处理数据,但第二个分区(最后两行)将数据读取为浮点数。这是因为第二列包含一个整数和一个浮点数,因此列类型被推断为浮点数。结果,7被解释为7.0,这与pandas的输出不同。
上述示例展示了包含str、int和float类型的异构数据导入, 但由其他数据/参数组合组成的异构数据也可能导致与pandas的数据类型不匹配。
解决方案
当检测到异构数据时,将发出警告。目前,Modin 并未正确处理这些差异,因此为了避免此问题,您需要手动设置 read_csv 的 dtype 参数,以在数据导入期间强制进行正确的数据类型转换。请注意,为了避免过多的性能下降,dtype 值应仅针对可能包含异构数据的列进行设置(仅为包含异构数据的列指定 dtype 参数)。
在大多数情况下,指定dtype参数会很好地工作。如果文件包含一个应被解释为索引的列(指定了index_col参数),索引中可能仍然存在类型差异,因为dtype参数仅负责数据字段。如果在上面的例子中,kwargs是这样设置的:
kwargs = {
"names": ["col1", "col2"],
"dtype": {"col1": str},
"index_col": "col1",
}
生成的Modin DataFrame将包含不正确的值 - 就像没有指定dtype一样:
col1
one 2
3 4
5 6
7.0 8
9.0 10
一种解决方法是导入数据时不设置index_col参数,然后使用DataFrame.set_index函数设置索引列,如下例所示:
pd_df = pd.read_csv(filename, dtype=data_dtype, index_col=None)
pd_df = pd_df.set_index(index_col_name)
pd_df.index.name = None
使用Modin与Python多进程#
我们强烈建议不要将分布式执行引擎(例如Ray或Dask)与Python多进程结合使用,因为这可能导致未定义的行为。下面展示了一个这样的例子:
import modin.pandas as pd
# Ray engine is used by default
df = pandas.DataFrame([1, 2, 3])
def f(arg):
return df + arg
if __name__ == '__main__':
from multiprocessing import Pool
with Pool(5) as p:
print(p.map(f, [1]))
尽管这个示例可能在您的机器上运行,但我们不推荐这样做,因为 Python 的 multiprocessing 库会复制 Ray 集群,导致 资源使用过度和可用资源的冲突。
使用Modin在Ray引擎上的首次操作性能较差#
在某些情况下,使用Modin在Ray引擎上的第一次操作可能比后续调用该操作要慢得多。这是因为在引擎初始化后,Ray工作节点可能还没有完全准备好进行计算,特别是在使用ray.init(runtime_env={'env_vars': {'__MODIN_AUTOIMPORT_PANDAS__': '1'}})初始化时,这是Modin在Ray引擎上的默认行为,如果Ray尚未初始化。Modin有意以这种方式初始化Ray,以便在Python解释器启动后在工作节点中导入pandas,从而避免Ray中导入线程和执行代码的线程之间的竞争条件。
import time
import pandas
import numpy as np
import ray
import modin.pandas as pd
import modin.config as cfg
# Look at the Ray documentation with respect to the Ray configuration suited to you most.
ray.init(runtime_env={'env_vars': {'__MODIN_AUTOIMPORT_PANDAS__': '1'}})
pandas_df = pandas.DataFrame(
np.random.randint(0, 100, size=(1000000, 13))
)
pandas_df.to_csv("foo.csv", index=False)
def read_csv_with_pandas():
start_time = time.time()
pandas_df = pandas.read_csv("foo.csv", index_col=0)
end_time = time.time()
pandas_duration = end_time - start_time
print("Time to read_csv with pandas: {} seconds".format(round(pandas_duration, 3)))
return pandas_df
def read_csv_with_modin():
start_time = time.time()
modin_df = pd.read_csv("foo.csv", index_col=0)
end_time = time.time()
modin_duration = end_time - start_time
print("Time to read_csv with Modin: {} seconds".format(round(modin_duration, 3)))
return modin_df
for i in range(5):
pandas_df = read_csv_with_pandas()
modin_df = read_csv_with_modin()
Time to read_csv with pandas: 0.708 seconds
Time to read_csv with Modin: 4.132 seconds
Time to read_csv with pandas: 0.735 seconds
Time to read_csv with Modin: 0.37 seconds
Time to read_csv with pandas: 0.646 seconds
Time to read_csv with Modin: 0.377 seconds
Time to read_csv with pandas: 0.673 seconds
Time to read_csv with Modin: 0.371 seconds
Time to read_csv with pandas: 0.672 seconds
Time to read_csv with Modin: 0.379 seconds
解决方案
到目前为止,除了不向ray.init()传递非空的runtime_env之外,还没有解决方案来修复或绕过这个问题。
然而,这可能会导致Ray中导入线程和执行代码的线程之间的竞争条件问题。
因此,目前我们只是强调这个问题,希望未来Ray本身能够修复。
此外,值得注意的是,每个分布式引擎本质上在首次调用操作时都会有一点开销,这对于微基准测试可能很重要。你可能想要做的是通过从测量中排除第一次迭代的时间来预热工作进程,或者在工作者中执行一个简单的函数以完全设置它们。
常见错误#
使用Dask引擎时出错:RuntimeError: if __name__ == '__main__':#
以下 script.py 使用 Modin 与 Dask 作为执行引擎并产生错误:
# script.py
import modin.pandas as pd
import modin.config as cfg
cfg.Engine.put("dask")
df = pd.DataFrame([0,1,2,3])
print(df)
上述脚本产生的一部分错误如下:
File "/path/python3.9/multiprocessing/spawn.py", line 134, in _check_not_importing_main
raise RuntimeError('''
RuntimeError:
An attempt has been made to start a new process before the
current process has finished its bootstrapping phase.
This probably means that you are not using fork to start your
child processes and you have forgotten to use the proper idiom
in the main module:
if __name__ == '__main__':
freeze_support()
...
The "freeze_support()" line can be omitted if the program
is not going to be frozen to produce an executable.
这是因为 Dask Client 使用 fork 来启动进程。
解决方案
为了避免这个问题,Dask Client 创建代码需要移动到模块的 __main__ 作用域中。
修正后的 script.py 看起来像:
# script.py
import modin.pandas as pd
import modin.config as cfg
cfg.Engine.put("dask")
if __name__ == "__main__":
df = pd.DataFrame([0, 1, 2, 3]) # Dask Client creation is hidden in the first call of Modin functionality.
print(df)
或
# script.py
from distributed import Client
import modin.pandas as pd
import modin.config as cfg
cfg.Engine.put("dask")
if __name__ == "__main__":
# Explicit Dask Client creation.
# Look at the Dask Distributed documentation with respect to the Client configuration suited to you most.
client = Client()
df = pd.DataFrame([0, 1, 2, 3])
print(df)
自定义Ray集群上出现虚假错误“无法导入部分初始化的pandas模块”#
如果您使用一些预配置的Ray集群来运行Modin,您可能会看到一些虚假的错误,例如
ray.exceptions.RaySystemError: System error: partially initialized module 'pandas' has no attribute 'core' (most likely due to a circular import)
traceback: Traceback (most recent call last):
File "/usr/share/miniconda/envs/modin/lib/python3.8/site-packages/ray/serialization.py", line 340, in deserialize_objects
obj = self._deserialize_object(data, metadata, object_ref)
File "/usr/share/miniconda/envs/modin/lib/python3.8/site-packages/ray/serialization.py", line 237, in _deserialize_object
return self._deserialize_msgpack_data(data, metadata_fields)
File "/usr/share/miniconda/envs/modin/lib/python3.8/site-packages/ray/serialization.py", line 192, in _deserialize_msgpack_data
python_objects = self._deserialize_pickle5_data(pickle5_data)
File "/usr/share/miniconda/envs/modin/lib/python3.8/site-packages/ray/serialization.py", line 180, in _deserialize_pickle5_data
obj = pickle.loads(in_band, buffers=buffers)
File "/usr/share/miniconda/envs/modin/lib/python3.8/site-packages/pandas/__init__.py", line 135, in <module>
from pandas import api, arrays, errors, io, plotting, testing, tseries
File "/usr/share/miniconda/envs/modin/lib/python3.8/site-packages/pandas/testing.py", line 6, in <module>
from pandas._testing import (
File "/usr/share/miniconda/envs/modin/lib/python3.8/site-packages/pandas/_testing/__init__.py", line 979, in <module>
cython_table = pd.core.common._cython_table.items()
AttributeError: partially initialized module 'pandas' has no attribute 'core' (most likely due to a circular import)
解决方案
Modin 包含一个解决方法,应该在工作进程启动时自动执行 import pandas。
它是由非空的__MODIN_AUTOIMPORT_PANDAS__环境变量的存在触发的,Modin在其启动的Ray集群上自动设置此变量,但在预配置的集群上可能缺失。
因此,如果您遇到如上所示的问题,请确保在实际生成工作节点之前,在集群的所有工作节点上设置此环境变量。