Tôi đang sử dụng phương pháp GDAL ReadAsArray để làm việc với dữ liệu raster bằng cách sử dụng numpy (cụ thể là phân loại lại). Vì các trình quét của tôi lớn, tôi xử lý các mảng trong các khối, lặp lại qua từng khối và xử lý bằng một phương thức tương tự như ví dụ GeoExamples .
Bây giờ tôi đang xem cách tốt nhất để đặt kích thước của các khối này để tối ưu hóa thời gian cần thiết để xử lý toàn bộ raster. Nhận thức được các hạn chế với kích thước mảng numpy và việc sử dụng GDAL GetBlockSize để sử dụng kích thước khối "tự nhiên" của raster, tôi đã thử nghiệm bằng cách sử dụng một vài kích thước khối khác nhau, tạo thành bội số của kích thước "tự nhiên", với mã ví dụ dưới đây:
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)
Mà tạo ra các loại đầu ra sau đây:
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
Tôi đã thử chạy nó cho một vài trình quét khác nhau, với các kích thước và loại pixel khác nhau và dường như có xu hướng tương tự, trong đó tăng gấp 10 lần kích thước x hoặc y (trong một số trường hợp, cả hai) giảm một nửa thời gian xử lý, điều này mặc dù không đáng kể trong ví dụ trên, có thể có nghĩa là một số phút cho các raster lớn nhất của tôi.
Vì vậy, câu hỏi của tôi là, tại sao hành vi này xảy ra?
Tôi đã mong đợi sử dụng ít khối hơn để cải thiện thời gian xử lý, nhưng các thử nghiệm sử dụng ít nhất không phải là nhanh nhất. Ngoài ra, tại sao bài kiểm tra cuối cùng lại mất nhiều thời gian hơn bài kiểm tra trước đó? Có một số loại ưu tiên với các trình quét để đọc theo hàng hoặc cột, hoặc trong hình dạng của khối được đọc, tổng kích thước? Điều tôi hy vọng nhận được từ điều này là thông tin để có được một thuật toán cơ bản cùng nhau để có thể đặt kích thước khối của raster thành một giá trị tối ưu, tùy thuộc vào kích thước của đầu vào.
Lưu ý rằng đầu vào của tôi là một raster lưới ESRI ArcINFO, có kích thước khối "tự nhiên" là 256 x 16 và tổng kích thước của raster của tôi trong ví dụ này là 41740 x 46280.