internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: cupy/cupy

Issue:
Don't set FFT work area when gained work area size is zero
`hipfftMakePlan1d` can output zero for the work area size, and given a null pointer returned by the allocator that supplied zero for the size, `hipfftSetWorkArea` (internally calls `rocfft_execution_info_set_work_buffer`) returns `HIPFFT_INVALID_VALUE`.

This PR fixes `Plan1d` not to set the work area pointer if the computed work area size is zero. Also `PlanNd` has the same fix.



Discussion:
I mistakenly pushed the branch to cupy repo instead of mine. Let me close this PR and post the correct one again.
Removed the branch.
Thanks!

Resolving patch:
diff --git a/cupy_setup_build.py b/cupy_setup_build.py
--- a/cupy_setup_build.py
+++ b/cupy_setup_build.py
@@ -115,6 +115,7 @@
         'libraries': [
             'amdhip64',  # was hiprtc and hip_hcc before ROCm 3.8.0
             'hipblas',
+            ('hipfft', lambda hip_version: hip_version >= 401),
             'hiprand',
             'rocfft',
             'roctx64',
@@ -452,6 +453,20 @@ def check_library(compiler, includes=(), libraries=(),
     return True
 
 
+def canonicalize_hip_libraries(hip_version, libraries):
+    def ensure_tuple(x):
+        return x if isinstance(x, tuple) else (x, None)
+    new_libraries = []
+    for library in libraries:
+        lib_name, pred = ensure_tuple(library)
+        if pred is None:
+            new_libraries.append(lib_name)
+        elif pred(hip_version):
+            new_libraries.append(lib_name)
+    libraries.clear()
+    libraries.extend(new_libraries)
+
+
 def preconfigure_modules(compiler, settings):
     """Returns a list of modules buildable in given environment and settings.
 
@@ -520,6 +535,21 @@ def preconfigure_modules(compiler, settings):
             if os.path.exists(lib_path):
                 settings['library_dirs'].append(lib_path)
 
+        # In ROCm 4.1 and later, we need to use the independent version of
+        # hipfft as well as rocfft. We configure the lists of include
+        # directories and libraries to link here depending on ROCm version
+        # before the configuration process following.
+        if use_hip and module['name'] == 'cuda':
+            if module['check_method'](compiler, settings):
+                hip_version = module['version_method']()
+                if hip_version >= 401:
+                    rocm_path = build.get_rocm_path()
+                    inc_path = os.path.join(rocm_path, 'hipfft', 'include')
+                    settings['include_dirs'].insert(0, inc_path)
+                    lib_path = os.path.join(rocm_path, 'hipfft', 'lib')
+                    settings['library_dirs'].insert(0, lib_path)
+                canonicalize_hip_libraries(hip_version, module['libraries'])
+
         print('')
         print('-------- Configuring Module: {} --------'.format(
             module['name']))


Test patch:
Repository: cupy/cupy

Issue:
Cosmetic bug: unnecessary print statement
There is an unwanted print statement in [denseToSparse](https://github.com/cupy/cupy/blob/51210b3daef66e5d2be1ebaa3a42ddc95c662146/cupy/cusparse.py#L1667), which keeps printing # nnz.
Please suppress it.

Thanks,
Rahul


Discussion:

Resolving patch:
diff --git a/cupy/cusparse.py b/cupy/cusparse.py
--- a/cupy/cusparse.py
+++ b/cupy/cusparse.py
@@ -1664,7 +1664,6 @@ def denseToSparse(x, format='csr'):
     _cusparse.spMatGetSize(desc_y.desc, num_rows_tmp.ctypes.data,
                            num_cols_tmp.ctypes.data, nnz.ctypes.data)
     nnz = int(nnz)
-    print('# nnz: {}'.format(nnz))
     if format == 'csr':
         indptr = y.indptr
         indices = _cupy.empty(nnz, 'i')


Test patch:
Repository: cupy/cupy

Issue:
Update docs for `cupy.linalg.eigh` and `cupy.linalg.eigvalsh`
https://docs.cupy.dev/en/stable/reference/generated/cupy.linalg.eigvalsh.html
> Calculates eigenvalues of a symmetric matrix.

https://numpy.org/doc/stable/reference/generated/numpy.linalg.eigvalsh.html
> Compute the eigenvalues of a complex Hermitian or real symmetric matrix.

Documentation needs to be updated as we already support Hermitian matrix in https://github.com/cupy/cupy/pull/1518.


Discussion:

Resolving patch:
diff --git a/cupy/linalg/_eigenvalue.py b/cupy/linalg/_eigenvalue.py
--- a/cupy/linalg/_eigenvalue.py
+++ b/cupy/linalg/_eigenvalue.py
@@ -66,10 +66,13 @@ def _syevd(a, UPLO, with_eigen_vector):
 
 
 def eigh(a, UPLO='L'):
-    """Eigenvalues and eigenvectors of a symmetric matrix.
+    """
+    Return the eigenvalues and eigenvectors of a complex Hermitian
+    (conjugate symmetric) or a real symmetric matrix.
 
-    This method calculates eigenvalues and eigenvectors of a given
-    symmetric matrix.
+    Returns two objects, a 1-D array containing the eigenvalues of `a`, and
+    a 2-D square array or matrix (depending on the input type) of the
+    corresponding eigenvectors (in columns).
 
     Args:
         a (cupy.ndarray): A symmetric 2-D square matrix ``(M, M)`` or a batch
@@ -111,11 +114,10 @@ def eigh(a, UPLO='L'):
 
 
 def eigvalsh(a, UPLO='L'):
-    """Calculates eigenvalues of a symmetric matrix.
+    """
+    Compute the eigenvalues of a complex Hermitian or real symmetric matrix.
 
-    This method calculates eigenvalues a given symmetric matrix.
-    Note that :func:`cupy.linalg.eigh` calculates both eigenvalues and
-    eigenvectors.
+    Main difference from eigh: the eigenvectors are not computed.
 
     Args:
         a (cupy.ndarray): A symmetric 2-D square matrix ``(M, M)`` or a batch


Test patch:
Repository: cupy/cupy

Issue:
Drop support for NumPy 1.17 in v10 (NEP 29)
CuPy should drop support for these legacy versions, following [NEP 29](https://numpy.org/neps/nep-0029-deprecation_policy.html#support-table).


Discussion:
Ah, SciPy 1.3 was already dropped 😅  Renamed the issue title.

As for SciPy, it seems there's no recommendation of supporting versions for downstream projects.

As we will support NumPy 1.18 in CuPy v10 (as recommended by NEP 29), I think it's better to continue supporting SciPy 1.4.0.
	
* NumPy 1.18.0 (released on Dec 23, 2019) https://pypi.org/project/numpy/#history
* SciPy 1.4.0 (released on Dec 17, 2019) https://pypi.org/project/scipy/#history

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -23,7 +23,7 @@
     'fastrlock>=0.5',
 ]
 install_requires = [
-    'numpy>=1.17,<1.24',  # see #4773
+    'numpy>=1.18,<1.24',  # see #4773
     'fastrlock>=0.5',
 ]
 extras_require = {


Test patch:
diff --git a/.pfnci/linux/tests/cuda102.Dockerfile b/.pfnci/linux/tests/cuda102.Dockerfile
--- a/.pfnci/linux/tests/cuda102.Dockerfile
+++ b/.pfnci/linux/tests/cuda102.Dockerfile
@@ -23,4 +23,4 @@ RUN pyenv install 3.7.11 && \
     pyenv global 3.7.11 && \
     pip install -U setuptools pip
 
-RUN pip install -U numpy==1.17.* scipy==1.4.* optuna==2.* cython==0.29.*
+RUN pip install -U numpy==1.18.* scipy==1.4.* optuna==2.* cython==0.29.*
diff --git a/.pfnci/linux/tests/cuda112.Dockerfile b/.pfnci/linux/tests/cuda112.Dockerfile
--- a/.pfnci/linux/tests/cuda112.Dockerfile
+++ b/.pfnci/linux/tests/cuda112.Dockerfile
@@ -19,4 +19,4 @@ RUN pyenv install 3.7.11 && \
     pyenv global 3.7.11 && \
     pip install -U setuptools pip
 
-RUN pip install -U numpy==1.17.* scipy==1.5.* optuna==2.* cython==0.29.*
+RUN pip install -U numpy==1.18.* scipy==1.5.* optuna==2.* cython==0.29.*
diff --git a/.pfnci/linux/tests/rocm-4-0.Dockerfile b/.pfnci/linux/tests/rocm-4-0.Dockerfile
--- a/.pfnci/linux/tests/rocm-4-0.Dockerfile
+++ b/.pfnci/linux/tests/rocm-4-0.Dockerfile
@@ -32,4 +32,4 @@ RUN pyenv install 3.7.11 && \
     pyenv global 3.7.11 && \
     pip install -U setuptools pip
 
-RUN pip install -U numpy==1.17.* scipy==1.4.* optuna==2.* cython==0.29.*
+RUN pip install -U numpy==1.18.* scipy==1.4.* optuna==2.* cython==0.29.*
Repository: cupy/cupy

Issue:
Enable cuTENSOR in elementwise operations
This can improve performance especially when tensors of different contiguity is given to binary operators, e.g., `c_cont_arr + f_cont_arr`.


Discussion:

Resolving patch:
diff --git a/cupy/_core/__init__.py b/cupy/_core/__init__.py
--- a/cupy/_core/__init__.py
+++ b/cupy/_core/__init__.py
@@ -4,8 +4,10 @@
 
 
 # internal APIs for testing and developement
+from cupy._core._accelerator import set_elementwise_accelerators  # NOQA
 from cupy._core._accelerator import set_reduction_accelerators  # NOQA
 from cupy._core._accelerator import set_routine_accelerators  # NOQA
+from cupy._core._accelerator import get_elementwise_accelerators  # NOQA
 from cupy._core._accelerator import get_reduction_accelerators  # NOQA
 from cupy._core._accelerator import get_routine_accelerators  # NOQA
 
diff --git a/cupy/_math/misc.py b/cupy/_math/misc.py
--- a/cupy/_math/misc.py
+++ b/cupy/_math/misc.py
@@ -253,7 +253,8 @@ def clip(a, a_min=None, a_max=None, out=None):
 
     .. seealso:: :data:`numpy.maximum`
 
-    ''')
+    ''',
+    cutensor_op=('OP_MAX', 1, 1))
 
 
 _float_minimum = ('out0 = (isnan(in0) | isnan(in1)) ? out0_type(NAN) : '
@@ -275,7 +276,8 @@ def clip(a, a_min=None, a_max=None, out=None):
 
     .. seealso:: :data:`numpy.minimum`
 
-    ''')
+    ''',
+    cutensor_op=('OP_MIN', 1, 1))
 
 
 fmax = _core.create_ufunc(


Test patch:
Repository: cupy/cupy

Issue:
Documentation of `cupy.linalg.cholesky()` needs update
It already supports batched version, but the doctoring was not updated, and I got an internal question about it:
https://github.com/cupy/cupy/blob/a8a042c129670b90bd04d1cfcbac2901bdcc9e4d/cupy/linalg/_decomposition.py#L161


Discussion:

Resolving patch:
diff --git a/cupy/linalg/_decomposition.py b/cupy/linalg/_decomposition.py
--- a/cupy/linalg/_decomposition.py
+++ b/cupy/linalg/_decomposition.py
@@ -158,10 +158,10 @@ def cholesky(a):
     transpose operator.
 
     Args:
-        a (cupy.ndarray): The input matrix with dimension ``(N, N)``
+        a (cupy.ndarray): The input matrix with dimension ``(..., M, M)``
 
     Returns:
-        cupy.ndarray: The lower-triangular matrix.
+        cupy.ndarray: The lower-triangular matrix of shape ``(..., M, M)``.
 
     .. warning::
         This function calls one or more cuSOLVER routine(s) which may yield


Test patch:
Repository: cupy/cupy

Issue:
Doc: Introduce `sphinx-copybutton`
### Description

Let's introduce https://sphinx-copybutton.readthedocs.io/en/latest/ to make snippets copiable.

### Additional Information

_No response_


Discussion:
Hi @kmaehashi! I can get this done quickly, please assign this issue to me 😃 
Sure, go ahead!
Hi @kmaehashi! Unfortunately testing my code changes is proving to be difficult on my MacBook (no NVIDIA GPU!). Feel free to give this issue to others.
Hi @prkhrsrvstv1 technically speaking to work on the doc builds you don't need any GPUs. If you install CuPy via
```
READTHEDOCS=True pip install -v -e .
```
CuPy can be built using stub headers and does not need the presence of either CUDA or HIP sw stack. In fact it's how the RTD environment was set up. You can check rendered htmls and so on. You just can't actually run any CuPy code this way. 

Let us know if this helps :)

Resolving patch:
diff --git a/docs/source/conf.py b/docs/source/conf.py
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -61,7 +61,8 @@
               'sphinx.ext.intersphinx',
               'sphinx.ext.mathjax',
               'sphinx.ext.napoleon',
-              'sphinx.ext.linkcode']
+              'sphinx.ext.linkcode',
+              'sphinx_copybutton']
 
 try:
     import sphinxcontrib.spelling  # noqa
@@ -149,6 +150,22 @@
 napoleon_use_ivar = True
 napoleon_include_special_with_doc = True
 
+# -- Copybutton settings --------------------------------------------------
+
+# Only copy lines starting with the input prompts,
+# valid prompt styles: [
+#     Python Repl + continuation (e.g., '>>> ', '... '),
+#     Bash (e.g., '$ '),
+#     ipython and qtconsole + continuation (e.g., 'In [29]: ', '  ...: '),
+#     jupyter-console + continuation (e.g., 'In [29]: ', '     ...: ')
+# ]
+# regex taken from https://sphinx-copybutton.readthedocs.io/en/latest/#using-regexp-prompt-identifiers
+copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: "
+copybutton_prompt_is_regexp = True
+
+# Continue copying lines as long as they end with this character
+copybutton_line_continuation_character = "\\"
+
 # -- Options for HTML output ----------------------------------------------
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for


Test patch:
Repository: cupy/cupy

Issue:
Improve `ImportError: CuPy is not correctly installed.` message
(AFAIK) This error message was introduced to prevent importing cupy from source tree without building it.
But today most users are using wheels or conda distributions, I think in most cases users see this error when there is a problem in users' CUDA installation.



Discussion:

Resolving patch:
diff --git a/cupy/__init__.py b/cupy/__init__.py
--- a/cupy/__init__.py
+++ b/cupy/__init__.py
@@ -16,26 +16,14 @@
 try:
     from cupy import _core  # NOQA
 except ImportError as e:
-    # _core is a c-extension module.
-    # When a user cannot import _core, it represents that CuPy is not correctly
-    # built.
-    _exc_info = _sys.exc_info()
-    _msg = ('''\
-CuPy is not correctly installed.
-
-If you are using wheel distribution (cupy-cudaXX), make sure that the version of CuPy you installed matches with the version of CUDA on your host.
-Also, confirm that only one CuPy package is installed:
-  $ pip freeze
-
-If you are building CuPy from source, please check your environment, uninstall CuPy and reinstall it with:
-  $ pip install cupy --no-cache-dir -vvvv
-
-Check the Installation Guide for details:
-  https://docs.cupy.dev/en/latest/install.html
-
-original error: {}'''.format(_exc_info[1]))  # NOQA
-
-    raise ImportError(_msg) from e
+    raise ImportError(f'''
+================================================================
+{_environment._diagnose_import_error()}
+
+Original error:
+  {type(e).__name__}: {e}
+================================================================
+''') from e
 
 
 from cupy import cuda  # NOQA
diff --git a/cupy/_environment.py b/cupy/_environment.py
--- a/cupy/_environment.py
+++ b/cupy/_environment.py
@@ -437,3 +437,17 @@ def _detect_duplicate_installation():
 
 --------------------------------------------------------------------------------
 ''')
+
+
+def _diagnose_import_error() -> str:
+    # TODO(kmaehashi): provide better diagnostics.
+    return '''\
+Failed to import CuPy.
+
+If you installed CuPy via wheels (cupy-cudaXXX or cupy-rocm-X-X), make sure that the package matches with the version of CUDA or ROCm installed.
+
+On Linux, you may need to set LD_LIBRARY_PATH environment variable depending on how you installed CUDA/ROCm.
+On Windows, try setting CUDA_PATH environment variable.
+
+Check the Installation Guide for details:
+  https://docs.cupy.dev/en/latest/install.html'''  # NOQA


Test patch:
Repository: cupy/cupy

Issue:
Eliminate `from os import path` from `cupy_setup_build.py`
Let's use `os.path` instead.


Discussion:

Resolving patch:
diff --git a/install/cupy_builder/cupy_setup_build.py b/install/cupy_builder/cupy_setup_build.py
--- a/install/cupy_builder/cupy_setup_build.py
+++ b/install/cupy_builder/cupy_setup_build.py
@@ -7,7 +7,6 @@
 from distutils import sysconfig
 from distutils import unixccompiler
 import os
-from os import path
 import shutil
 import sys
 
@@ -44,7 +43,7 @@ def module_extension_name(file):
 
 def module_extension_sources(file, use_cython, no_cuda):
     pyx, others = ensure_module_file(file)
-    base = path.join(*pyx.split('.'))
+    base = os.path.join(*pyx.split('.'))
     pyx = base + ('.pyx' if use_cython else '.cpp')
 
     # If CUDA SDK is not available, remove CUDA C files from extension sources
@@ -281,9 +280,9 @@ def make_extensions(ctx: Context, compiler, use_cython):
     include_dirs = settings['include_dirs']
 
     settings['include_dirs'] = [
-        x for x in include_dirs if path.exists(x)]
+        x for x in include_dirs if os.path.exists(x)]
     settings['library_dirs'] = [
-        x for x in settings['library_dirs'] if path.exists(x)]
+        x for x in settings['library_dirs'] if os.path.exists(x)]
 
     # Adjust rpath to use CUDA libraries in `cupy/.data/lib/*.so`) from CuPy.
     use_wheel_libs_rpath = (
@@ -498,7 +497,7 @@ def cythonize(extensions, ctx: Context):
 def check_extensions(extensions):
     for x in extensions:
         for f in x.sources:
-            if not path.isfile(f):
+            if not os.path.isfile(f):
                 raise RuntimeError('''\
 Missing file: {}
 Please install Cython.


Test patch:
Repository: cupy/cupy

Issue:
Incorrect output of `cupy.logaddexp()`
For this case, mathematically we should get `inf`, but CuPy returns `nan`:
```python
>>> np.logaddexp(np.inf, np.inf)
inf
>>>
>>> cp.logaddexp(np.inf, np.inf)
array(nan)

```
The reason is `in0-in1` gives `nan` when both are `inf`, and it propagates all the way out:
https://github.com/cupy/cupy/blob/4469fae998df33c72ff40ef954cb08b8f0004b18/cupy/_math/explog.py#L73




Discussion:
Note: this relates to the `test_indexing.py` failure seen in https://github.com/cupy/cupy/pull/5698#issuecomment-913406882.

Resolving patch:
diff --git a/cupy/_math/explog.py b/cupy/_math/explog.py
--- a/cupy/_math/explog.py
+++ b/cupy/_math/explog.py
@@ -70,7 +70,14 @@
 logaddexp = _core.create_ufunc(
     'cupy_logaddexp',
     ('ee->e', 'ff->f', 'dd->d'),
-    'out0 = fmax(in0, in1) + log1p(exp(-fabs(in0 - in1)))',
+    '''
+    if (in0 == in1) {
+        /* Handles infinities of the same sign */
+        out0 = in0 + log(2.0);
+    } else {
+        out0 = fmax(in0, in1) + log1p(exp(-fabs(in0 - in1)));
+    }
+    ''',
     doc='''Computes ``log(exp(x1) + exp(x2))`` elementwise.
 
     .. seealso:: :data:`numpy.logaddexp`
@@ -81,7 +88,14 @@
 logaddexp2 = _core.create_ufunc(
     'cupy_logaddexp2',
     ('ee->e', 'ff->f', 'dd->d'),
-    'out0 = fmax(in0, in1) + log2(1 + exp2(-fabs(in0 - in1)))',
+    '''
+    if (in0 == in1) {
+        /* Handles infinities of the same sign */
+        out0 = in0 + 1.0;
+    } else {
+        out0 = fmax(in0, in1) + log2(1 + exp2(-fabs(in0 - in1)));
+    }
+    ''',
     doc='''Computes ``log2(exp2(x1) + exp2(x2))`` elementwise.
 
     .. seealso:: :data:`numpy.logaddexp2`


Test patch:
diff --git a/tests/cupy_tests/math_tests/test_explog.py b/tests/cupy_tests/math_tests/test_explog.py
--- a/tests/cupy_tests/math_tests/test_explog.py
+++ b/tests/cupy_tests/math_tests/test_explog.py
@@ -1,12 +1,10 @@
-import unittest
-
 import numpy
+import pytest
 
 from cupy import testing
 
 
-@testing.gpu
-class TestExplog(unittest.TestCase):
+class TestExplog:
 
     @testing.for_all_dtypes()
     @testing.numpy_cupy_allclose(atol=1e-5)
@@ -54,5 +52,19 @@ def test_log1p(self):
     def test_logaddexp(self):
         self.check_binary('logaddexp', no_complex=True)
 
+    @pytest.mark.parametrize('val', [numpy.inf, -numpy.inf])
+    @testing.for_float_dtypes()
+    @testing.numpy_cupy_allclose()
+    def test_logaddexp_infinities(self, xp, dtype, val):
+        a = xp.full((2, 3), val, dtype=dtype)
+        return xp.logaddexp(a, a)
+
     def test_logaddexp2(self):
         self.check_binary('logaddexp2', no_complex=True)
+
+    @pytest.mark.parametrize('val', [numpy.inf, -numpy.inf])
+    @testing.for_float_dtypes()
+    @testing.numpy_cupy_allclose()
+    def test_logaddexp2_infinities(self, xp, dtype, val):
+        a = xp.full((2, 3), val, dtype=dtype)
+        return xp.logaddexp2(a, a)
Repository: cupy/cupy

Issue:
compile_with_cache no longer returns result
I think there was a mistake when this function was refactored to include the deprecation message.  Previously, it returned the compilation result.  Now it calls `_compile_module_with_cache`, but the return value is ignored. 


Discussion:

Resolving patch:
diff --git a/cupy/cuda/compiler.py b/cupy/cuda/compiler.py
--- a/cupy/cuda/compiler.py
+++ b/cupy/cuda/compiler.py
@@ -457,7 +457,7 @@ def compile_with_cache(*args, **kwargs):
         'cupy.cuda.compile_with_cache has been deprecated in CuPy v10, and'
         ' will be removed in the future. Use cupy.RawModule or cupy.RawKernel'
         ' instead.', DeprecationWarning)
-    _compile_module_with_cache(*args, **kwargs)
+    return _compile_module_with_cache(*args, **kwargs)
 
 
 def _compile_module_with_cache(


Test patch:
diff --git a/tests/cupy_tests/cuda_tests/test_compiler.py b/tests/cupy_tests/cuda_tests/test_compiler.py
--- a/tests/cupy_tests/cuda_tests/test_compiler.py
+++ b/tests/cupy_tests/cuda_tests/test_compiler.py
@@ -2,6 +2,8 @@
 import unittest
 from unittest import mock
 
+import pytest
+
 import cupy
 from cupy.cuda import compiler
 from cupy import testing
@@ -125,3 +127,12 @@ def test(self):
         e2 = pickle.loads(pickle.dumps(e1))
         assert e1.args == e2.args
         assert str(e1) == str(e2)
+
+
+class TestCompileWithCache:
+    def test_compile_module_with_cache(self):
+        compiler._compile_module_with_cache('__device__ void func() {}')
+
+    def test_deprecated_compile_with_cache(self):
+        with pytest.warns(DeprecationWarning):
+            compiler.compile_with_cache('__device__ void func() {}')
Repository: cupy/cupy

Issue:
Add `numpy.typing` equivalent APIs in CuPy
This will allow adding type annotations to CuPy's codebase (#4831) and users' code.

https://numpy.org/devdocs/reference/typing.html


Discussion:

Resolving patch:
diff --git a/cupy/typing/__init__.py b/cupy/typing/__init__.py
new file mode 100644
--- /dev/null
+++ b/cupy/typing/__init__.py
@@ -0,0 +1,4 @@
+from cupy.typing._generic_alias import ArrayLike  # NOQA
+from cupy.typing._generic_alias import DTypeLike  # NOQA
+from cupy.typing._generic_alias import NBitBase  # NOQA
+from cupy.typing._generic_alias import NDArray  # NOQA
diff --git a/cupy/typing/_generic_alias.py b/cupy/typing/_generic_alias.py
new file mode 100644
--- /dev/null
+++ b/cupy/typing/_generic_alias.py
@@ -0,0 +1,30 @@
+import sys
+from typing import Any, TypeVar
+
+import numpy
+
+import cupy
+
+
+if numpy.lib.NumpyVersion(numpy.__version__) >= '1.20.0':
+    from numpy.typing import ArrayLike  # NOQA
+    from numpy.typing import DTypeLike  # NOQA
+    from numpy.typing import NBitBase  # NOQA
+else:
+    ArrayLike = Any
+    DTypeLike = Any
+    NBitBase = Any
+
+
+if sys.version_info >= (3, 9):
+    from types import GenericAlias
+elif numpy.lib.NumpyVersion(numpy.__version__) >= '1.21.0':
+    from numpy.typing import _GenericAlias as GenericAlias
+else:
+    def GenericAlias(*args):
+        return Any
+
+
+_ScalarType = TypeVar("ScalarType", bound=numpy.generic, covariant=True)
+_DType = GenericAlias(numpy.dtype, (_ScalarType,))
+NDArray = GenericAlias(cupy.ndarray, (Any, _DType))


Test patch:
diff --git a/tests/cupy_tests/test_typing.py b/tests/cupy_tests/test_typing.py
new file mode 100644
--- /dev/null
+++ b/tests/cupy_tests/test_typing.py
@@ -0,0 +1,8 @@
+import cupy
+
+
+class TestClassGetItem:
+
+    def test_class_getitem(self):
+        from typing import Any
+        cupy.ndarray[Any, Any]