Repository: modin-project/modin

Issue:
Enable range-partitioning implementation for `groupby().rolling()` by default
Doing measurements, I found out that using range-partitioning implementation for `groupby().rolling()` is always faster than full-axis implementation, so it's worth enabling range-partitioning impl by default for this case (the same as we did for `groupby().apply()` #6804)

<details><summary>16 cores</summary>

![image](https://github.com/modin-project/modin/assets/62142979/3597b23a-23c2-4d01-98fa-66b07606ea4e)

</details>

<details><summary>44 cores</summary>

![image](https://github.com/modin-project/modin/assets/62142979/e30a9bc4-2827-464b-8ce5-aa30f2e7ba09)

</details>

<details><summary>script to measure</summary>

```python
import modin.pandas as pd
import pandas

import numpy as np

import modin.config as cfg
from timeit import default_timer as timer
from modin.utils import execute

NROWS = [10_000, 30_000, 50_000, 100_000, 500_000, 1_000_000, 5_000_000]
NCOLS = [10, 40]
NGROUPS = [10, 10_000]
USE_RANGE_PART = [True, False]
NITERS = 3
WINDOW = 5
method = "mean"

total_iters = len(NROWS) * len(NCOLS) * len(NGROUPS) * len(USE_RANGE_PART) * NITERS
its = 0

res_s = pandas.DataFrame(index=pandas.Index(NROWS, name="num_rows"), columns=pandas.MultiIndex.from_product([NCOLS, NGROUPS, USE_RANGE_PART], names=["num_cols", "num_groups", "use range-part"]))

for nrows in NROWS:
    for ncols in NCOLS:
        for ngroups in NGROUPS:
            data = {
                "key": np.tile(np.arange(ngroups), nrows // ngroups),
                **{f"data_col{i}": np.random.randint(0, 1_000_000, size=nrows) for i in range(ncols - 1)}
            }

            for use_rpart in USE_RANGE_PART:
                cfg.RangePartitioningGroupby.put(use_rpart)
                md_df = pd.DataFrame(data)
                execute(md_df)
                times = []
                for i in range(NITERS):
                    print(f"{round((its / total_iters) * 100, 2)}%")
                    t1 = timer()
                    res = getattr(md_df.groupby("key").rolling(WINDOW), method)()
                    execute(res)
                    md_time = timer() - t1
                    times.append(md_time)
                    its += 1
                tm = np.median(times)
                res_s.loc[nrows, (ncols, ngroups, use_rpart)] = tm

                res_s.to_excel("rolling.xlsx")
```

</details>


Discussion:

Resolving patch:
diff --git a/modin/core/storage_formats/pandas/query_compiler.py b/modin/core/storage_formats/pandas/query_compiler.py
--- a/modin/core/storage_formats/pandas/query_compiler.py
+++ b/modin/core/storage_formats/pandas/query_compiler.py
@@ -3993,23 +3993,30 @@ def agg_func(window, *args, **kwargs):
         else:
             assert callable(agg_func)
 
-        if unsupported_groupby:
-            obj = super(PandasQueryCompiler, self)
-        else:
-            obj = self
-
-        return obj.groupby_agg(
-            by=by,
-            agg_func=lambda grp, *args, **kwargs: agg_func(
+        kwargs = {
+            "by": by,
+            "agg_func": lambda grp, *args, **kwargs: agg_func(
                 grp.rolling(**rolling_kwargs), *args, **kwargs
             ),
-            axis=axis,
-            groupby_kwargs=groupby_kwargs,
-            agg_args=agg_args,
-            agg_kwargs=agg_kwargs,
-            how="direct",
-            drop=drop,
-        )
+            "axis": axis,
+            "groupby_kwargs": groupby_kwargs,
+            "agg_args": agg_args,
+            "agg_kwargs": agg_kwargs,
+            "how": "direct",
+            "drop": drop,
+        }
+
+        if unsupported_groupby:
+            return super(PandasQueryCompiler, self).groupby_agg(**kwargs)
+
+        try:
+            return self._groupby_shuffle(**kwargs)
+        except NotImplementedError as e:
+            get_logger().info(
+                f"Can't use range-partitioning groupby implementation because of: {e}"
+                + "\nFalling back to a full-axis implementation."
+            )
+            return self.groupby_agg(**kwargs)
 
     def groupby_agg(
         self,


Test patch: