2

ランダムなデータで大きなファイルを作成するタスクがあります。私は次のコードでやり始めました:

from __future__ import print_function

N=10
rand_file = open("file_name", 'w');

for i in range(1, 7000000):
  print(''.join(random.choice(string.ascii_lowercase)
                for x in range(N)),
        file=rand_file)

このプログラムを使用してディスク上で得られる書き込みスループットを見ると、これが最速の方法ではないと感じます。100MB の連続したバッファー スペースを作成し、バッファーに文字列を書き込み、バッファーがいっぱいになるたびにそれをファイルにフラッシュしたいと考えています。Pythonでこれを行う方法は?io.BufferedWriter を見ましたが、それを使用してファイルに書き込む方法がわかりませんでした。

どんな提案でも大歓迎です。ありがとう。

4

5 に答える 5

3

価値のあるものとして、これに BufferedWriter を使用する例を次に示します。

import io
import random
import string

N=10
rand_file = io.FileIO("file_name", 'w')
writer = io.BufferedWriter(rand_file,buffer_size=100000000)

for i in range(1, 7000000):
  writer.write(''.join(random.choice(string.ascii_lowercase) for x in range(N)))

writer.flush()
于 2013-10-02T15:37:41.963 に答える
2

ファイルのバッファ サイズを増やすことができます。デフォルトでは、わずか 8k で、大量にフラッシュされます。

import random
import time
import string

N = 10
count = 0

start = time.time()
with open('/tmp/xyz','wb',100*(2**20)) as f:
    for i in xrange(1,7000000):
        s = ''.join(random.choice(string.ascii_lowercase) for x in range(N))
        count += len(s)
        f.write(s)
delta = time.time() - start
print count/(2**20), 'mb', count/(delta*(2**20)), 'mbs'

これにより、大規模な連続書き込みを行うことができます。これは一般的には良いことですが、パフォーマンスはそれほど向上しません。random.choice() の計算を維持してみてください。ただし、コード内の印刷は省略してください。それでも時間がかかります。IO バウンドではなく、CPU バウンドです。

于 2013-10-02T16:03:59.730 に答える
0

これを試して大きなファイルを作成すると、書き込みが速くなるはずです:

import random

N = 2**20

f = open('rand.txt', 'wb')
f.seek(N-1)
f.write('\0')
f.seek(0)

for i in xrange(N-1):
    f.write(chr(random.randint(32,127)))

f.close()
于 2013-10-02T15:05:00.893 に答える
0

ascii_lowerandchoiceの代わりにstringand をインポートするとrandom、実行時間が短縮されます。
ステートメントを使用しwithてファイルを開くと、実行時間がわずかに増加する原因のようです。

7000 行 (私のコードでは 7000000 の代わりにこの番号を使用しました) を書く代わりに、最後のコードのアイデアは\n、ファイルにこの文字列を出力する前にリンクされている文字列内の行数をグループ化することです。
そうすることで、 への呼び出し回数print()が減ります。

行の総数の約数ではないグループ化された行の数と同じ総行数を取得するには、for ループと xrange でいくつかのトリッキーな計算を行う必要があります (コードを見て理解することをお勧めします)。 .

また、1024 の倍数でありながら、複数の行をグループ化する文字列のビット数と等しくなるようにバッファー サイズを選択しました
。ファイルの各行には 10 文字が含まれている必要があります。グループ化された行は で連結されます\n--> 11 文字になります。\n最後にグループ化された行の後にはありませんが、print()動作するときにそのような文字が追加され`\nます。
したがって、グループ化されたn行の場合、グループ化文字列にはn * 11 文字があります。文字==8 ビットとして、n *11*8 = n *88 とします。次に n を見つけるのは簡単です: nを検証する必要があります*88 = buffer_size。buffer_size の 1024 の倍数と 88 の倍数を同時に取得する必要があります。

編集

バッファのサイズを調整しようとしてもメリットがないようです。

from __future__ import print_function

from time import clock
from os.path import getsize

N=10
A,B,C,D,E,F = [],[],[],[],[],[]
repet = 20
total_lines = 7000

.

import random
import string
for i in xrange(repet):
  te = clock()
  rand_file1 = open("file_name1", 'w')
  for i in range(total_lines):
    print(''.join(random.choice(string.ascii_lowercase)
                  for x in range(N)),
          file=rand_file1)
  rand_file1.close()
  A.append(clock()-te)

.

import random
import string
for i in xrange(repet):
  te = clock()
  with open("file_name2", 'w') as rand_file2:
    for i in range(total_lines):
      print(''.join(random.choice(string.ascii_lowercase)
                    for x in range(N)),
            file=rand_file2)
  B.append(clock()-te)

.

import random
from string import ascii_lowercase
for i in xrange(repet):
  te = clock()
  rand_file3 = open("file_name3", 'w')
  for i in range(total_lines):
    print(''.join(random.choice(ascii_lowercase)
                  for x in range(N)),
          file=rand_file3)
  rand_file3.close()
  C.append(clock()-te)

.

from random import choice
from string import ascii_lowercase
for i in xrange(repet):
  te = clock()
  rand_file4 = open("file_name4", 'w')
  for i in range(total_lines):
    print(''.join(choice(ascii_lowercase)
                  for x in range(N)),
          file=rand_file4)
  rand_file4.close()
  D.append(clock()-te)

.

from random import choice
from string import ascii_lowercase
buffer_size = 22528
grouped_lines = buffer_size/(11*8)
for i in xrange(repet):
  te = clock()
  rand_file5 = open("file_name5", 'w') # <== no buffer's size adjusted here
  for i in range(0, total_lines, grouped_lines):
    u = '\n'.join(''.join(choice(ascii_lowercase)
                            for x in range(N))
                  for y in xrange(min(grouped_lines,total_lines-i)))
    print(u,file=rand_file5)
  rand_file5.close()
  E.append(clock()-te)

.

from random import choice
from string import ascii_lowercase
buffer_size = 22528
grouped_lines = buffer_size/(11*8)
for i in xrange(repet):
  te = clock()
  rand_file6 = open("file_name6", 'w', buffer_size)
  for i in range(0, total_lines, grouped_lines):
    u = '\n'.join(''.join(choice(ascii_lowercase)
                            for x in range(N))
                  for y in xrange(min(grouped_lines,total_lines-i)))
    print(u,file=rand_file6)
  rand_file6.close()
  F.append(clock()-te)

.

t1,t2,t3,t4,t5,t6=map(min,(A,B,C,D,E,F))
print ('1  %s\n'
       '2  %s  %.3f %%\n'
       '3  %s  %.3f %%\n'
       '4  %s  %.3f %%\n'
       '5  %s  %.3f %%\n'
       '6  %s  %.3f %%\n'
       % (t1,
          t2,t2/t1*100,
          t3,t3/t1*100,
          t4,t4/t1*100,
          t5,t5/t1*100,
          t6,t6/t1*100))


for y in xrange(880,100000,88):
  if y%1024==0:
    print('%d %% 88 == %d   %d %% 1024 == %d'
          % (y,y%88,y,y%1024))

print("\nfile_name1",getsize('file_name1'))
for fn in ("file_name2","file_name3",
           "file_name4","file_name5",
           "file_name6"):
  print(fn,getsize(fn))

結果

1  0.492455605391
2  0.503463149646  102.235 %
3  0.475755717556  96.609 %
4  0.449807168229  91.340 %
5  0.319271024669  64.832 %
6  0.334138277351  67.851 %

11264 % 88 == 0   11264 % 1024 == 0
22528 % 88 == 0   22528 % 1024 == 0
33792 % 88 == 0   33792 % 1024 == 0
45056 % 88 == 0   45056 % 1024 == 0
56320 % 88 == 0   56320 % 1024 == 0
67584 % 88 == 0   67584 % 1024 == 0
78848 % 88 == 0   78848 % 1024 == 0
90112 % 88 == 0   90112 % 1024 == 0

file_name1 84000
file_name2 84000
file_name3 84000
file_name4 84000
file_name5 84000
file_name6 84000  
于 2013-10-02T22:40:53.023 に答える
-3

Python は、ランダム データを含む大きなファイルを作成するための最も簡単または最速の方法であるとは限りません。次の bash スニペットは、指定された長さのファイルをランダム データで作成します。ソースについては、この質問を参照してください。

dd if=/dev/random iflag=fullblock of=$HOME/randomFile bs=1M count=1
于 2014-07-10T02:10:19.090 に答える