ENH: Add separate numba kernels for groupby aggregations
- [ ] closes #xxxx (Replace xxxx with the GitHub issue number)
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [ ] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.

This PR adds separate groupby numba kernels, since the old shared kernels with Window required an expensive sort beforehand.

e.g. look at this snakeviz (pay attention to the ``take`` call. for reference, ``column_looper`` is the part doing the actual aggregation)

![KPgbLhJsIxi4U9L7gyqBZ8TaJbgkSqg34gItFRdnMNZYnl_SFElErHYCdVtS9BD82yn2EHepAQ9P60-dbUtaXhSp3DSIe-_u8hOscAGnKFVBMCN0MKj-u7ccNK4f](https://github.com/pandas-dev/pandas/assets/47963215/56aa84f5-d310-4aed-9526-eb2975a799f2)

Benchmarks
```
       before           after         ratio
     [43d12a23]       [6cf83167]
                      <groupby-numba-kernels>
-         197±5ms         66.6±1ms     0.34  groupby.GroupByNumbaAgg.time_frame_agg('float64', 'sum')
-         234±4ms       77.5±0.7ms     0.33  groupby.GroupByNumbaAgg.time_frame_agg('float64', 'var')
-         221±2ms       65.2±0.7ms     0.30  groupby.GroupByNumbaAgg.time_frame_agg('float64', 'mean')
-       20.1±0.1s         54.3±1ms     0.00  groupby.GroupByNumbaAgg.time_frame_agg('float64', 'max')
-       20.3±0.2s       54.3±0.8ms     0.00  groupby.GroupByNumbaAgg.time_frame_agg('float64', 'min')
```

Compared to Cython, we are still ~2x slower, but I think I can get back some more perf (would be a follow up PR).

If ``parallel=True`` is passed, though, we can be around ~2x faster than our Cython impl, though.

(This is on a Intel 2019 MBP, Intel core i7-9750H w/ 16 GB RAM)

cc @jbrockmendel if interested.
(You and I talked about parallelism in pandas a couple weeks back).
While there is a nice speedup here, I am a little concerned about proliferating implementations of reductions in the spirit of https://github.com/pandas-dev/pandas/issues/53261 > While there is a nice speedup here, I am a little concerned about proliferating implementations of reductions in the spirit of #53261

The problem is the numba kernels are basically useless without this.

I was doing a little benchmarking a little while back and numba was ~5x slower than Cython before this change.
Because the majority of time is spent in the sorting overhead, this means that even running the numba aggregations in parallel doesn't really provide a speedup.

With these kernels at least, I think we can share the Kahan summation part for ``sum``/``mean``/``var``. 
I could probably also reimplement ``mean`` in terms of sum, so the impact of this shouldn't be too horrible. Gentle ping 
@jbrockmendel @mroeschke @rhshadrach > If parallel=True is passed, though, we can be around ~2x faster than our Cython impl, though.

Is this one of the use cases where there is a prospect of parallelizing the cython version too?
 > Is this one of the use cases where there is a prospect of parallelizing the cython version too?

In the near future, no, since shipping openmp in wheels is a PITA. 
I think we need an openmp runtime package/wheel or something to depend on on PyPI before moving forwards with parallelizing Cython.

numba seems to at least have figured out how to solve this problem partially. I think you can use the tbb backend if installing with pip and on conda-forge you can choose between tbb/openmp. no objection in principle, will defer to matt since he's more involved in manitaining this code @mroeschke 
Do you have time to take a look at this soon?

(I'd like to get this in, if not the apply stuff, at least for 2.1) Thanks @lithomas1 