私はGDALのReadAsArrayメソッドを使用して、numpy(具体的には再分類)を使用してラスターデータを処理しています。ラスターが大きいため、配列をブロックで処理し、各ブロックを反復処理して、GeoExamplesの例と同様の方法で処理します。
これらのブロックのサイズを設定して、ラスター全体の処理にかかる時間を最適化する方法を検討しています。numpy配列サイズの制限と、ラスタの「自然な」ブロックサイズを使用するためのGDAL GetBlockSizeの使用に注意して、「自然な」サイズの倍数で構成されるいくつかの異なるブロックサイズを使用してテストしました。以下のサンプルコードで:
import timeit
try:
import gdal
except:
from osgeo import gdal
# Function to read the raster as arrays for the chosen block size.
def read_raster(x_block_size, y_block_size):
raster = "path to large raster"
ds = gdal.Open(raster)
band = ds.GetRasterBand(1)
xsize = band.XSize
ysize = band.YSize
blocks = 0
for y in xrange(0, ysize, y_block_size):
if y + y_block_size < ysize:
rows = y_block_size
else:
rows = ysize - y
for x in xrange(0, xsize, x_block_size):
if x + x_block_size < xsize:
cols = x_block_size
else:
cols = xsize - x
array = band.ReadAsArray(x, y, cols, rows)
del array
blocks += 1
band = None
ds = None
print "{0} blocks size {1} x {2}:".format(blocks, x_block_size, y_block_size)
# Function to run the test and print the time taken to complete.
def timer(x_block_size, y_block_size):
t = timeit.Timer("read_raster({0}, {1})".format(x_block_size, y_block_size),
setup="from __main__ import read_raster")
print "\t{:.2f}s\n".format(t.timeit(1))
raster = "path to large raster"
ds = gdal.Open(raster)
band = ds.GetRasterBand(1)
# Get "natural" block size, and total raster XY size.
block_sizes = band.GetBlockSize()
x_block_size = block_sizes[0]
y_block_size = block_sizes[1]
xsize = band.XSize
ysize = band.YSize
band = None
ds = None
# Tests with different block sizes.
timer(x_block_size, y_block_size)
timer(x_block_size*10, y_block_size*10)
timer(x_block_size*100, y_block_size*100)
timer(x_block_size*10, y_block_size)
timer(x_block_size*100, y_block_size)
timer(x_block_size, y_block_size*10)
timer(x_block_size, y_block_size*100)
timer(xsize, y_block_size)
timer(x_block_size, ysize)
timer(xsize, 1)
timer(1, ysize)
次のような出力が生成されます。
474452 blocks size 256 x 16:
9.12s
4930 blocks size 2560 x 160:
5.32s
58 blocks size 25600 x 1600:
5.72s
49181 blocks size 2560 x 16:
4.22s
5786 blocks size 25600 x 16:
5.67s
47560 blocks size 256 x 160:
4.21s
4756 blocks size 256 x 1600:
5.62s
2893 blocks size 41740 x 16:
5.85s
164 blocks size 256 x 46280:
5.97s
46280 blocks size 41740 x 1:
5.00s
41740 blocks size 1 x 46280:
800.24s
サイズとピクセルタイプが異なるいくつかの異なるラスターに対してこれを実行してみましたが、xまたはy次元が10倍(場合によっては両方)増加すると処理時間が半分になり、同様の傾向が得られているようです上記の例ではそれほど重要ではありませんが、私の最大のラスターの分数を意味する場合があります。
だから私の質問は、なぜこの行動が起こっているのですか?
処理時間を改善するために使用するブロックを少なくすることを期待していましたが、最小限のテストは最も速くはありません。また、最終テストが先行テストよりもはるかに長いのはなぜですか?行または列ごとに、または読み取られるブロックの形状で合計サイズを読み取るために、ラスターに何らかの好みがありますか?これから得たいのは、入力のサイズに応じて、ラスターのブロックサイズを最適な値に設定できる基本的なアルゴリズムをまとめるための情報です。
入力はESRI ArcINFOグリッドラスタであり、「自然な」ブロックサイズは256 x 16であり、この例のラスタの合計サイズは41740 x 46280でした。