タイマ分解能精度評価(C++)

# 概要

C++のタイマの分解能の精度に対してどのくらい誤差があるのかを測定してみた．

:::note info
**分解能**
タイマが測定可能な時間粒度を指す．
:::

# 測定
分解能の測定方法は参考資料[2]の3章に記載されている方法を参考にした．
使用したプログラムは参考資料[3]に対して複数の分解能を収集するように改造した．

:::note info
収集した分解能に対して，箱ひげ図の表示と基本統計量の算出を行った。
:::

:::note warn
githubには精度測定用のプログラムはアップしていない．
:::
:::note warn
タイマのカウント更新タイミングが悪いせいなのか大きくブレてしまっている箇所がある．
:::


**分解能とレイテンシーの測定方法**

https://qiita.com/Ocean0000/items/19d9a81a2af12fe890e0

## Windows
Windowsのタイマは分解能のバラつきが少なく安定性の高いタイマが多い印象であった．

* 開発環境：
    * Visual Studio 2022 community
* PCスペック：
    * OS:Windows10 Pro(64bit)
    * CPU:Intel(R)Core(TM) i9-109000X 3.70Ghz(物理コア数：10, 論理コア数：20)
    * メインメモリ:128GB

### ナノ秒タイマ
![nano.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1025492/ade9661b-6ed9-1491-7b90-e29dec1841c0.png)
**基本統計量(10,000サンプル)**

|                                |    mean |     std | min | 25% | 50% | 75% |    max |
|------------------------------:|--------:|--------:|----:|----:|----:|----:|-------:|
|           chrono::system_clock | 105.550 | 554.999 | 100 | 100 | 100 | 100 | 55,600 |
|           chrono::steady_clock | 101.310 | 116.844 | 100 | 100 | 100 | 100 | 11,700 |
| GetSystemTimePreciseAsFileTime | 100.060 |   5.999 | 100 | 100 | 100 | 100 |    700 |
|        QueryPerformanceCounter | 100.190 |  19.000 | 100 | 100 | 100 | 100 |  2,000 |
|                   timespec_get | 100.110 |  10.999 | 100 | 100 | 100 | 100 |  1,200 |
|        GetSystemTimeAsFileTime | 996.942 |  10.258 | 836 | 997 | 997 | 997 |  1,158 |

:::note info
単位：ナノ秒
:::

### ミリ秒タイマ
![milisec.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1025492/6ca192c9-be75-ef36-b9f1-ac27557622be.png)

**基本統計量(10,000サンプル)**

|                |   mean |   std | min | 25% | 50% | 75% | max |
|---------------:|-------:|------:|----:|----:|----:|----:|----:|
|          clock |  1.000 | 0.000 |   1 |   1 |   1 |   1 |   1 |
|   GetTickCount | 15.625 | 0.484 |  15 |  15 |  16 |  16 |  16 |
| GetTickCount64 | 15.625 | 0.484 |  15 |  15 |  16 |  16 |  16 |
|    timeGetTime |  1.000 | 0.014 |   1 |   1 |   1 |   1 |   2 |

:::note info
単位：ミリ秒
:::

::: note warn
timeGetTimeはtimeBeginPeriod(1)を使用
:::

:::note alert
clockはCPU時間である．
:::

### 秒タイマ
![second.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1025492/1620700b-7fbe-ead7-2127-985ab4559d64.png)

**基本統計量(200サンプル)**

|      |  mean |   std | min | 25% | 50% | 75% | max |
|-----:|------:|------:|----:|----:|----:|----:|----:|
| time | 1.000 | 0.000 |   1 |   1 |   1 |   1 |   1 |

:::note info
単位：秒
:::

# Mac
Macのタイマは分解能のバラつきが多くて不安定なタイマが多い印象であった．

* 開発環境：
    * Xcode 13.2.1
* PCスペック：
    * OS:macOS Montery(Mac mini(M1 2020))
    * CPU:Apple M1
    * メインメモリ:16GB

### ナノ秒タイマ
![nano.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1025492/49098409-adce-24cb-6712-4514b26c9251.png)

**基本統計量(10,000サンプル)**

|                                           |        mean |         std |   min |   25% |    50% |    75% |       max |
|------------------------------------------:|------------:|------------:|------:|------:|-------:|-------:|----------:|
|                      chrono::system_clock |   1,004.900 |     204.157 | 1,000 | 1,000 |  1,000 |  1,000 |    12,000 |
|                      chrono::steady_clock |      44.395 |      10.538 |    41 |    41 |     42 |     42 |       167 |
|             clock_gettime(CLOCK_REALTIME) |   1,000.000 |       0.000 | 1,000 | 1,000 |  1,000 |  1,000 |     1,000 |
|            clock_gettime(CLOCK_MONOTONIC) |   1,000.300 |      29.999 | 1,000 | 1,000 |  1,000 |  1,000 |     4,000 |
|        clock_gettime(CLOCK_MONOTONIC_RAW) |      41.728 |       2.581 |    41 |    41 |     42 |     42 |       167 |
| clock_gettime(CLOCK_MONOTONIC_RAW_APPROX) | 100,029.387 | 328,585.735 |    42 | 4,375 | 11,770 | 31,875 | 1,992,792 |
|           clock_gettime(CLOCK_UPTIME_RAW) |      41.752 |       2.833 |    41 |    41 |     42 |     42 |       209 |
|    clock_gettime(CLOCK_UPTIME_RAW_APPROX) | 248,853.979 | 549,319.202 |   417 | 6,791 | 21,125 | 71,135 | 1,995,833 |
|   clock_gettime(CLOCK_PROCESS_CPUTIME_ID) |   1,066.000 |     248.294 | 1,000 | 1,000 |  1,000 |  1,000 |     2,000 |
|    clock_gettime(CLOCK_THREAD_CPUTIME_ID) |     140.300 |      20.182 |    83 |   125 |    125 |    166 |       209 |
|                              timespec_get |   1,000.000 |       0.000 | 1,000 | 1,000 |  1,000 |  1,000 |     1,000 |

:::note info
単位：ナノ秒
:::

:::note alert
clock_gettime(CLOCK_PROCESS_CPUTIME_ID), clock_gettime(CLOCK_THREAD_CPUTIME_ID)はCPU時間である．
:::

### マイクロ秒タイマ
![micro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1025492/a34d9ba2-8997-4b81-a36d-af84839735ef.png)

**基本統計量(10,000サンプル)**

|              | mean  | std   | min | 25% | 50% | 75% | max |
|-------------:|------:|------:|----:|----:|----:|----:|----:|
|        clock | 1.067 | 0.453 |   1 |   1 |   1 |   1 |  39 |
| gettimeofday | 1.000 | 0.030 |   1 |   1 |   1 |   1 |   4 |

:::note info
単位：マイクロ秒
:::

:::note alert
clockはCPU時間である．
:::

### 秒タイマ
![second.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1025492/0b979da8-fcf5-8f87-02b2-e4418d05236e.png)

**基本統計量(200サンプル)**

|      |  mean |   std | min | 25% | 50% | 75% | max |
|-----:|------:|------:|----:|----:|----:|----:|----:|
| time | 1.000 | 0.000 |   1 |   1 |   1 |   1 |   1 |

:::note info
単位：秒
:::
 
# 参考資料
1. cpprefjp - C++日本語リファレンス, https://cpprefjp.github.io
1. Optimized C++ ―最適化、高速化のためのプログラミングテクニック, Kurt Guntheroth (著), 島 敏博 (監修), 黒川 利明 (翻訳), オライリージャパン, 2017年2月.
1. 性能評価プログラム, https://github.com/Ocean00000/TimeEvaluation
1. 碧色工房, https://www.mm2d.net/main/