R03/03/12
R03/03/13 追記を追記
追記
スクリプトやプログラムは実験用で作成していますので、このままでは実用性はありません。
またMac Pro (Late 2013) の内蔵ストレージでは効果がありますが、SSD 系のストレージでも並列書込が遅い物では効果がありません。正確には早くなるどころか遅くなる可能性も大きいです。またインターネット共有を使っていますが何故か早いのは下りのみです。
Shell Script とPython Script に分かれているのは、最初はPython のglob やPathlib でコピー元ファイルリストを取得していたのですが、何故か30 Sec 以上かかる状況だったためのです。LAN 越しだと遅くなるようです。
下記にコピーしたファイル群の諸元を書き込んでおきます。
File Size Average: 16.40MB
File Size Median: 14MB
File Size Max: 912MB
File Size Min: 13MB
File Size STDEV.P(Excel): 20.67
6760 Files
素人が作っています。動作は保証できません。
また、ファイルの上書きには十分ご注意を。
Python プログラムとShell Script を使ってフォルダ内の6760 ファイルを6 並列でコピーします。
結果:
4Gbps 程度を達成しました。cp -R でコピーすると2Gbps 程度。Finder では1Gbps 程度でした。
Mac Pro (Late 2013) macOS Big Sur 11.2.2
Python 3.8.5
Thunderbolt ブリッジ。インターネット共有使用。クライアント側からダウンロード。
Thunderbolt ブリッジのネゴシエーションは10Gbps
コピーするファイルは1 フォルダに6760 ファイル。総容量は「116,207,272,052 Byte」。ほとんどがデジタルカメラの写真ファイルです。
経緯の説明:
事の発端は例えば50GB のファイルをThunderbolt ブリッジでコピーする際に、cp コマンで単純にやるより10GB に5 分割してcp & cp & cp & cp & cp と5 コピーを同時に行った方が総合計50GB を転送するのが早かったことです。
分割で送る場合は、分割の手間と結合の時間がかかりますから実行上は、分割しても早くはなりません。
しかしならが初めから、ある程度の大きさのファイルが大量にフォルダに入っている状況であれば、転送速度の点では分割コピーと同じ結果が得られる可能性があるのではと予想しました。
プログラムの動作に責任はもてません。
1.
「FileListtxt2OP.sh」 でコピーするファイルのリストを作成します。「src」にコピーしたフォルダのパスを設定してください。
「writef」に設定されたファイルに、「src」内のファイルパスを書き出します。同盟のファイルがあると上書きされます。
コピーするのはファイルのみです。
2.
「Copyop.py」で「FileListtxt2OP.sh」で作成したファイルを並列コピーします。「1.」で作成したファイルのパスを「path」に設定してください。
コピー先は「dst」に設定。同盟のファイルがあると上書きされます。
3.
下記でコピーします。
FileListtxt2OP.sh && Copyop.py
FileListtxt2OP.sh
#!/bin/bash
# 「src」はコピー元ファイルが保存されているフォルダのパスです。「writef」はそのパスを保存するファイルです。
src="/Volumes/apple/Pictures/CopyTestFile"
writef="/Users/apple/Desktop/testR333.txt"
# 「src」からファイルパスを取得します。「._」で始まるファイルは除外しています。
find $src -type f -not -name '._*' > "$writef"
Copyop.py
#!/usr/bin/env python3
import shutil
from multiprocessing import Pool
import os
# cpC は並列コピーの数です。例えば「4」にすると4 並列でコピーします。
cpC = 6
# 「testR333.txt」と言う名前のファイルからコピー元ファイルのパスを取得します。
# dst はコピー先のPathです。
path = '/Users/apple/Desktop/testR333.txt'
dst = '/Users/apple/Pictures/dst'
# ファイルをコピーする関数です。並列処理に使います。
def fileTrans(src, dst):
shutil.copy2(src, dst)
# 「fileTrans(src, dst)」が変数を2 つ持つためラッパーを使って変数を渡します。
def wrapper_fileTrans(args):
return fileTrans(*args)
# 「testR333.txt」を開きfilesPath に読み込みます。splitlines を「\n」を削除しています。
with open(path) as f:
filesPath = [s.splitlines() for s in f.readlines()]
# ラッパーに渡すリストcpx を作ります。「['コピー元', 'コピー先']」を二次元リストで作っているだけです。
cpx = [[filesPath[x][0], dst] for x in range(len(filesPath))]
# 動作確認用にcpx をprint しているだけです。なくても問題ないです。
for i in range(len(cpx)):
print(cpx[i])
print("xyz")
# Copy を並列処理します。
if __name__ == "__main__":
p = Pool(processes=cpC)
p.map(wrapper_fileTrans, cpx)
p.close()