Repository: cupy/cupy

Issue:
Cupyx.profiler benchmark method to.str returns inconsistent formats.
### Description

Hi,

I am currently benchmarking cupy code and by reading the docs, I found that one should use the built-in ```cupyx.profiler``` benchmark. When calling benchmark on a Callable this returns an object of type ```_PerfCaseResult```. In order to post-process the results, I use the method ```to.str()```. However, this method inconsistently returns lists of different lengths which is problematic. 



### To Reproduce
```
import cupy as cp
import sys
from cupyx.profiler import benchmark
import cupyx.scipy.ndimage

def generate_matrix(size, work_units):
    rand = cp.random.default_rng()                            
    mat = rand.integers(0, 100_000, (size, size, work_units)) 
    return mat

def generate_array(size, work_units):
    rand = cp.random.default_rng()                            
    arr = rand.integers(0, 100_000, (size, work_units)) 
    return arr


def rotate(mat):
    y = cupyx.scipy.ndimage.rotate(mat, angle = 90) 
    sz = y.shape
    return 

def multiply(arr):
    y = cp.multiply(arr, 42)
    sz = len(y)
    return 
    

if __name__ == '__main__':
    sz = 100
    wk = 1_000
    mat = generate_matrix(sz, wk)  
    arr = generate_array(sz, wk)

    k = benchmark(rotate, (mat, ), n_repeat=20, n_warmup = 5)
    j = benchmark(multiply, (arr, ), n_repeat=20, n_warmup = 5)
    print(len(k.to_str(show_gpu=1).split())) #List of length 16
    print(len(j.to_str(show_gpu=1).split())) #List of length 24
```

### Installation

```
conda create -n rps -c rapidsai -c nvidia -c conda-forge  \
    rapids=22.10 python=3.9 cudatoolkit=11.5
```

### Environment

```
OS                           : Linux-5.15.0-52-generic-x86_64-with-glibc2.35
Python Version               : 3.9.13
CuPy Version                 : 10.6.0
CuPy Platform                : NVIDIA CUDA
NumPy Version                : 1.22.4
SciPy Version                : 1.9.1
Cython Build Version         : 0.29.30
Cython Runtime Version       : None
CUDA Root                    : /home/joachim/anaconda3/envs/rps
nvcc PATH                    : None
CUDA Build Version           : 11020
CUDA Driver Version          : 11070
CUDA Runtime Version         : 11050
cuBLAS Version               : (available)
cuFFT Version                : 10600
cuRAND Version               : 10207
cuSOLVER Version             : (11, 3, 2)
cuSPARSE Version             : (available)
NVRTC Version                : (11, 5)
Thrust Version               : 101000
CUB Build Version            : 101000
Jitify Build Version         : 87d8ccd
cuDNN Build Version          : None
cuDNN Version                : None
NCCL Build Version           : 21212
NCCL Runtime Version         : 21403
cuTENSOR Version             : None
cuSPARSELt Build Version     : None
Device 0 Name                : NVIDIA GeForce GTX 1660 SUPER
Device 0 Compute Capability  : 75
Device 0 PCI Bus ID          : 0000:01:00.0
```


### Additional Information

_No response_


Discussion:

Resolving patch:
diff --git a/cupyx/profiler/_time.py b/cupyx/profiler/_time.py
--- a/cupyx/profiler/_time.py
+++ b/cupyx/profiler/_time.py
@@ -50,9 +50,9 @@ def _to_str_per_item(device_name, t):
         assert t.size > 0
         t_us = t * 1e6
 
-        s = '    {}:{:9.03f} us'.format(device_name, t_us.mean())
+        s = '    {}: {:9.03f} us'.format(device_name, t_us.mean())
         if t.size > 1:
-            s += '   +/-{:6.03f} (min:{:9.03f} / max:{:9.03f}) us'.format(
+            s += '   +/- {:6.03f} (min: {:9.03f} / max: {:9.03f}) us'.format(
                 t_us.std(), t_us.min(), t_us.max())
         return s
 


Test patch:
diff --git a/tests/cupyx_tests/profiler_tests/test_benchmark.py b/tests/cupyx_tests/profiler_tests/test_benchmark.py
--- a/tests/cupyx_tests/profiler_tests/test_benchmark.py
+++ b/tests/cupyx_tests/profiler_tests/test_benchmark.py
@@ -90,10 +90,10 @@ def test_show_gpu(self):
         perf = _time._PerfCaseResult('test_name_xxx', times, (0,))
         expected = (
             'test_name_xxx       :'
-            '    CPU:    5.620 us   +/- 0.943 '
-            '(min:    4.200 / max:    7.100) us '
-            '    GPU-0:    6.600 us   +/- 2.344 '
-            '(min:    3.800 / max:    9.600) us'
+            '    CPU:     5.620 us   +/-  0.943 '
+            '(min:     4.200 / max:     7.100) us '
+            '    GPU-0:     6.600 us   +/-  2.344 '
+            '(min:     3.800 / max:     9.600) us'
         )
         assert str(perf) == expected
 
@@ -105,8 +105,8 @@ def test_no_show_gpu(self):
         perf = _time._PerfCaseResult('test_name_xxx', times, (0,))
         expected = (
             'test_name_xxx       :'
-            '    CPU:    5.620 us   +/- 0.943 '
-            '(min:    4.200 / max:    7.100) us'
+            '    CPU:     5.620 us   +/-  0.943 '
+            '(min:     4.200 / max:     7.100) us'
         )
         assert perf.to_str() == expected
         # Checks if the result does not change.
@@ -115,18 +115,18 @@ def test_no_show_gpu(self):
     def test_single_show_gpu(self):
         times = numpy.array([[5.4], [6.4]]) * 1e-6
         perf = _time._PerfCaseResult('test_name_xxx', times, (0,))
-        assert str(perf) == ('test_name_xxx       :    CPU:    5.400 us '
-                             '    GPU-0:    6.400 us')
+        assert str(perf) == ('test_name_xxx       :    CPU:     5.400 us '
+                             '    GPU-0:     6.400 us')
 
     def test_single_no_show_gpu(self):
         times = numpy.array([[5.4], [6.4]]) * 1e-6
         perf = _time._PerfCaseResult('test_name_xxx', times, (0,))
-        assert perf.to_str() == 'test_name_xxx       :    CPU:    5.400 us'
+        assert perf.to_str() == 'test_name_xxx       :    CPU:     5.400 us'
 
     def test_show_multigpu(self):
         times = numpy.array([[5.4], [6.4], [7.0], [8.1]]) * 1e-6
         perf = _time._PerfCaseResult('test_name_xxx', times, (0, 1, 2))
-        assert str(perf) == ('test_name_xxx       :    CPU:    5.400 us '
-                             '    GPU-0:    6.400 us '
-                             '    GPU-1:    7.000 us '
-                             '    GPU-2:    8.100 us')
+        assert str(perf) == ('test_name_xxx       :    CPU:     5.400 us '
+                             '    GPU-0:     6.400 us '
+                             '    GPU-1:     7.000 us '
+                             '    GPU-2:     8.100 us')
diff --git a/tests/cupyx_tests/test_time.py b/tests/cupyx_tests/test_time.py
--- a/tests/cupyx_tests/test_time.py
+++ b/tests/cupyx_tests/test_time.py
@@ -89,10 +89,10 @@ def test_show_gpu(self):
         perf = cupyx.time._PerfCaseResult('test_name_xxx', times, (0,))
         expected = (
             'test_name_xxx       :'
-            '    CPU:    5.620 us   +/- 0.943 '
-            '(min:    4.200 / max:    7.100) us '
-            '    GPU-0:    6.600 us   +/- 2.344 '
-            '(min:    3.800 / max:    9.600) us'
+            '    CPU:     5.620 us   +/-  0.943 '
+            '(min:     4.200 / max:     7.100) us '
+            '    GPU-0:     6.600 us   +/-  2.344 '
+            '(min:     3.800 / max:     9.600) us'
         )
         assert str(perf) == expected
 
@@ -104,8 +104,8 @@ def test_no_show_gpu(self):
         perf = cupyx.time._PerfCaseResult('test_name_xxx', times, (0,))
         expected = (
             'test_name_xxx       :'
-            '    CPU:    5.620 us   +/- 0.943 '
-            '(min:    4.200 / max:    7.100) us'
+            '    CPU:     5.620 us   +/-  0.943 '
+            '(min:     4.200 / max:     7.100) us'
         )
         assert perf.to_str() == expected
         # Checks if the result does not change.
@@ -114,18 +114,18 @@ def test_no_show_gpu(self):
     def test_single_show_gpu(self):
         times = numpy.array([[5.4], [6.4]]) * 1e-6
         perf = cupyx.time._PerfCaseResult('test_name_xxx', times, (0,))
-        assert str(perf) == ('test_name_xxx       :    CPU:    5.400 us '
-                             '    GPU-0:    6.400 us')
+        assert str(perf) == ('test_name_xxx       :    CPU:     5.400 us '
+                             '    GPU-0:     6.400 us')
 
     def test_single_no_show_gpu(self):
         times = numpy.array([[5.4], [6.4]]) * 1e-6
         perf = cupyx.time._PerfCaseResult('test_name_xxx', times, (0,))
-        assert perf.to_str() == 'test_name_xxx       :    CPU:    5.400 us'
+        assert perf.to_str() == 'test_name_xxx       :    CPU:     5.400 us'
 
     def test_show_multigpu(self):
         times = numpy.array([[5.4], [6.4], [7.0], [8.1]]) * 1e-6
         perf = cupyx.time._PerfCaseResult('test_name_xxx', times, (0, 1, 2))
-        assert str(perf) == ('test_name_xxx       :    CPU:    5.400 us '
-                             '    GPU-0:    6.400 us '
-                             '    GPU-1:    7.000 us '
-                             '    GPU-2:    8.100 us')
+        assert str(perf) == ('test_name_xxx       :    CPU:     5.400 us '
+                             '    GPU-0:     6.400 us '
+                             '    GPU-1:     7.000 us '
+                             '    GPU-2:     8.100 us')