Python xử lý các tệp lớn như thế nào?
Những gì chúng ta đã thấy cho đến nay hầu hết hợp lệ khi xử lý các tệp dữ liệu “nhỏ”. Nhỏ nghĩa là bất kỳ kích thước nào mà máy tính xách tay của bạn có thể xử lý ngày hôm nay trong một khoảng thời gian “hợp lý”… Trong bài học này, mục tiêu của chúng tôi là cho bạn thấy cách giới thiệu xử lý song song có thể tăng tốc công việc xử lý dữ liệu của bạn. Khi xử lý các tệp rất lớn, máy tính xách tay hoặc máy chủ cục bộ của bạn không đủ và bạn cần chuyển công việc của mình sang cơ sở hạ tầng máy tính dữ liệu quốc gia hoặc châu Âu. Bài học sơ bộ này nhằm mục đích dạy cho bạn những điểm chính đối với việc sử dụng các cơ sở lớn hơn. Tuy nhiên, chúng tôi vẫn sử dụng tài nguyên điện toán cục bộ i. e. máy tính xách tay của riêng bạn nhưng chúng tôi đặc biệt khuyến khích bạn kiểm tra và dùng thử trên các cơ sở máy tính lớn hơn Show
Đọc các tệp netCDF-4 hoặc HDF-5 có kích thước trung bình đến lớn Trước tiên, chúng tôi cần tạo một bộ dữ liệu netCDF “lớn hơn”;
Và chúng tôi thêm dữ liệu bổ sung vào thứ nguyên không giới hạn của nó (thời gian) %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close() Như bạn có thể thấy việc ghi tập dữ liệu này khá chậm… nhưng sau này chúng ta sẽ xem cách chúng ta có thể cải thiện hiệu suất khi ghi tệp netCDF như thế nào. Trước tiên, chúng tôi xem cách chúng tôi có thể đọc tệp này trên máy tính xách tay có bộ nhớ %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()8 Đọc một lát của tập dữ liệuKhi tệp netCDF của bạn trở nên lớn, bạn khó có thể đưa toàn bộ tệp vào bộ nhớ máy tính xách tay của mình. Bạn có thể cắt tập dữ liệu của mình và tải nó để nó có thể vừa với bộ nhớ máy tính xách tay của bạn. Bạn có thể cắt các biến netCDF bằng cú pháp tương tự như mảng có nhiều mảng %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()
Thời gian đã trôi qua để trích xuất lát cắt của bạn phụ thuộc rất nhiều vào cách dữ liệu của bạn được lưu trữ (cách tổ chức các thứ nguyên) %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # print some metadata print(d) d.close()
Trong trường hợp của chúng tôi, thứ nguyên %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()9 thay đổi chậm nhất và thứ nguyên %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()0 là nhanh nhất **Nguồn. http. //www. thống nhất dữ liệu. ucar. edu/blogs/developer/entry/chunking_data_why_it_matters ** Lý do là khi lưu trữ tập dữ liệu của chúng tôi, chúng tôi đã sử dụng bố cục lưu trữ netCDF mặc định. e. bố cục lưu trữ liền kề (thứ tự chỉ mục) thông thường Vì vậy, tùy thuộc vào cách bạn muốn truy cập (để xử lý hậu kỳ hoặc trực quan hóa) dữ liệu của mình, đây có thể là cách tiếp cận tốt nhất hoặc tệ nhất Một sự thỏa hiệp tốt là sử dụng phân đoạn, lưu trữ dữ liệu đa chiều trong các khối hình chữ nhật đa chiều để tăng tốc độ truy cập chậm với chi phí làm chậm truy cập nhanh. Các chương trình truy cập dữ liệu chunked có thể không biết chunking được sử dụng như thế nào. Chunking được hỗ trợ trong lớp HDF5 của tệp netCDF-4 và là một trong những tính năng, cùng với tính năng nén theo từng đoạn, dẫn đến đề xuất sử dụng HDF5 làm lớp lưu trữ cho netCDF-4 vào năm 2002 **Nguồn. http. //www. thống nhất dữ liệu. ucar. edu/blogs/developer/entry/chunking_data_why_it_matters ** Nếu bạn muốn tìm hiểu thêm về chủ đề này, hãy đọc blog này tại đây
netCDF/HDF Nén dữ liệuNgoài việc phân đoạn dữ liệu, bạn có thể nén các biến netCDF/HDF một cách nhanh chóng. HDF5 thường có thể dễ dàng đạt đến mức nén rất tốt khi sử dụng thư viện %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()1 (để có được chức năng này, netCDF-4 và HDF5 cần được biên dịch với thư viện %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()1) Hãy lấy tệp %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()3 trước đây của chúng tôi và viết lại nó bằng cách nén %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()2 Điện toán song song để phân tích dữ liệu không gian-thời gian. bóng tối dask. một thư viện tính toán song song linh hoạt cho tính toán phân tíchChúng tôi thường có tập dữ liệu lớn để xử lý; . Việc sử dụng python như chúng ta đã làm cho đến nay không thể thực hiện được nữa
Chúng tôi đã thấy rằng việc phân đoạn dữ liệu rất hiệu quả nhưng việc viết chương trình mà chúng tôi vừa phân đoạn dữ liệu vừa xử lý có thể rất cồng kềnh. Và để tăng tốc quá trình xử lý của chúng tôi, chúng tôi cần sử dụng nhiều hơn một bộ xử lý, vì vậy chúng tôi cần một khung đủ đơn giản và hiệu quả trên quy mô lớn Dask là một thư viện python giúp tính toán song song trên khối dữ liệu lớn. Điều này cho phép phân tích dữ liệu không vừa với bộ nhớ máy tính của bạn cũng như tận dụng khả năng đa xử lý của máy Xem phần giới thiệu Dask rất hay. Điện toán song song bằng Python do Matthew Rocklin thực hiện tại Hội nghị dữ liệu Strata 2017 Hãy xem cách nó hoạt động với một ví dụ %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()6 %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()7 Cho đến nay, chúng tôi vừa mở một tệp HDF5 bằng %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()6 (gói này là API mức rất thấp để đọc các tệp HDF5; nó thường rất hiệu quả) và đọc %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()7 (Mật độ cột dọc của Ozone). Đó là trường 2D, vì vậy khi chúng tôi tạo một mảng %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()8, chúng tôi có thể tách nó ra %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()0 Chúng tôi chưa tính toán bất cứ điều gì vì tất cả các hoạt động với %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()8 đều bị hoãn lại. Nhưng chúng ta đã có thể thấy tập hợp các thao tác cần thiết để tính giá trị lớn nhất %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()1 Bạn phải nhìn hình từ dưới lên trên. Ở dưới cùng, bạn thấy tất cả các khối của mình (ở đây là 10) và ở trên cùng là kết quả cuối cùng (giá trị tối đa của toàn bộ trường) %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()2 %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()3 Ở đây, tập hợp các hoạt động được tuần tự hóa vì chúng tôi không chạy nó trên máy tính đa bộ xử lý nhưng với những thay đổi đáng kể, bạn có thể chạy mã tương tự với các tệp lớn và trên một số lượng lớn bộ xử lý Và ngay cả trên máy tính xách tay của bạn, %matplotlib inline from netCDF4 import Dataset d = Dataset('large.nc', 'r') # Do not load dataset yet data=d.variables['VO'] # pick-up a time and read VO slice_t=data[1000,:,:,:] d.close()8 có thể rất hữu ích vì nó cho phép các hoạt động ngoài lõi. Điều này có nghĩa là nếu tệp của bạn không vừa với bộ nhớ của máy tính, bạn vẫn có thể chạy thao tác lớn trên tệp đó; Hãy lấy một ví dụ khác %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()4 %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()5 %matplotlib inline from netCDF4 import Dataset import numpy as np # Read and Append to an existing netCDF file d = Dataset('large.nc', 'a') data=d.variables['VO'] t=d.variables['time'] last_time=t[t.size-1] VO=data[0,:,:,:] appendvar = d.variables['VO'] for nt in range(t.size,t.size+50): # there are 100 times in the file originally VO += 0.1 * np.random.randn() last_time += 6.0 appendvar[nt] = VO t[nt] = last_time d.close()6
|