LoginSignup
2
1

More than 1 year has passed since last update.

MacBook Pro (M1 Pro 10 Core)の実力

Posted at

はじめに

2021年10月に発売されたMacBook Proを購入したので、今まで使用していた2013年のMacBook Proと処理時間を比較してみました。結論を先に言ってしまうと、その早さに驚愕です。

MacBook Pro 2013 MacBook Pro 2021
PC MacBook Pro (Retina, 13-inch, Late 2013) MacBook Pro (14インチ、2021)
CPU 2.6GHz デュアルコアIntel Core i5 Apple M1 Pro
Memory 8GB 16GB
OS macOS Big Sur (11.6) macOS Monterey (12.0.1)
Python 3.8 3.9

プログラムの説明

8607社の株式の時系列データを下記計算式にフィットさせaの値を求めます。

y = e^{ax}

データを正規化するために、x=0のとき、y=1となるうようにデータを調整しています。1銘柄に対して、2011年から2016年、2012年から2017年、・・・、2017年から2021年のようにして7期間のaを算出して、結果をExcelファイルに出力してます。
起動時の引数としてワーカー数を指定します。concurrent.futuresにこのワーカー数を指定して並列処理をさせます。

プログラムは下記のようになります。

import sys
import concurrent.futures
import numpy as np
from scipy.optimize import curve_fit
import pandas as pd
import stocktools

PERIOD_FROM = '2011-01-01'
PERIOD_TO = '2021-09-30'
PERIODS = [
    ['2011-01-01', '2015-12-31'],
    ['2012-01-01', '2016-12-31'],
    ['2013-01-01', '2017-12-31'],
    ['2014-01-01', '2018-12-31'],
    ['2015-01-01', '2019-12-31'],
    ['2016-01-01', '2020-12-31'],
    ['2017-01-01', '2021-09-30'],
]


def analyze_period(df_all, from_date, to_date):
    def func(x: int, a: int) -> int:
        return a ** x

    df = df_all[from_date: to_date].copy()
    if len(df) == 0:
        return None

    # 初期値が1となるように正規化
    if df['close'].iloc[0] == 0:
        df['close'] = df['close'] + 1
    df['nclose'] = df['close'] / df['close'].iloc[0]
    df['days'] = [x.days for x in df.index - df.index[0]]

    param, cov = curve_fit(func, df['days'], df['nclose'])
    df['pred'] = [func(x, param[0]) for x in df['days']]
    df['delta'] = df['nclose'] / df['pred'] - 1
    mse = np.sqrt(np.sum(df['delta'] ** 2))
    mse = mse / df['pred'].iloc[-1]

    result = {'base': param[0],
              'nclose': df['nclose'][-1],
              'pred': df['pred'][-1],
              'mse': mse}
    return result


def analyze(ticker):
    # print(f'{ticker}')

    data = stocktools.get_stock(ticker, PERIOD_FROM, PERIOD_TO)
    if data is None or len(data) == 0:
        return None

    df = data[['Close']].copy()
    df.columns = ['close']

    result = {'ticker': ticker}
    for i, period in enumerate(PERIODS):
        r = analyze_period(df, period[0], period[1])
        if r is not None:
            r2 = {}
            for key in r.keys():
                r2[f'{key}_{i}'] = r[key]
            result.update(r2)
    return result


def main():
    if len(sys.argv) != 2:
        max_workers = None
    else:
        max_workers = int(sys.argv[1])

    df_list = stocktools.get_stock_list()

    with concurrent.futures.ProcessPoolExecutor(max_workers=max_workers) as executer:
        results = executer.map(analyze, list(df_list.index))

    df = pd.DataFrame([x for x in results if x is not None])
    df.to_pickle('result.pkl')
    df.to_excel('result.xlsx', index=None)


if __name__ == '__main__':
    main()

stocktoolsというのは自前のツールで、株価の時系列データを取得するものです。時系列データは事前にダウンロードしています。

測定方法

ワーカー数を1からPCのCore数まで増やして測定していきます。
Core数は下記で求めました。

import os
print(os.cpu_count())

MacBook Pro 2013では4、MacBook Pro 2021では10となります。

測定結果

単位は秒です。

Max Workers MacBook 2013 MacBook 2021
1 1333.275 267.186
2 683.213 145.021
3 634.725 101.219
4 608.148 77.986
5 63.899
6 54.719
7 48.195
8 43.393
9 42.079
10 41.673

perf.png

MacBook Pro 2013では4Core使って608秒かかる計算が、MacBook Pro 2021では1Coreで267秒で2.2倍高速、4Core使うと78秒となり7.7倍高速になっています。10Core全て使うと42秒となり15倍くらい高速化されてます。

最後に

測定結果から分かりますが、1Core(並列処理を意識しない作り)だとその差は5倍くらいとなります。これだけでも十分早いのですが、10Coreを生かすために並列処理とすることで15倍くらい高速化できました。24時間以上かかるような計算をすることもあるので、うまく作れば数時間で終わらせることができるかも知れません。

測定していて気づいたことですが、MacBook Pro 2013はファンの音がすごくうるさかったのに対して、2021はほぼ無音でした。キーボードも温かくなりません。

実は2台のPCでTensorFlowでDeepLearningさせたのですが、こちらは性能差が4〜5倍でした。先に書いた通り、これは1Coreでの性能差となってます。バッチサイズを調整すればもう少し早くなるかも知れません。こちらについてはおいおい確かめようと思ってます。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1