[ad_1]
Một bản phát hành gần đây của Julia chẳng hạn như 1.10 được khuyến khích. Đối với những người muốn sử dụng máy tính xách tay, kho được chia sẻ ở trên cũng chứa tệp Pluto. Sao Diêm Vương.jl cần phải được cài đặt. Tệp dữ liệu đầu vào cho thử thách là duy nhất cho mọi người và cần được tạo bằng cách sử dụng tập lệnh Python này. Hãy nhớ rằng tệp có kích thước khoảng 15 GB.
python3 create_measurements.py 1000000000
Ngoài ra, chúng tôi sẽ chạy điểm chuẩn bằng cách sử dụng Điểm chuẩnTools.jl bưu kiện. Lưu ý rằng điều này không ảnh hưởng đến thử thách mà chỉ nhằm mục đích thu thập số liệu thống kê thích hợp để đo lường và định lượng hiệu suất của mã Julia.
Cấu trúc file dữ liệu đầu vào measurements.txt
như sau (chỉ hiển thị năm dòng đầu tiên):
attipūdi;-49.2
Bas Limbé;-43.8
Oas;5.6
Nesebar;35.9
Saint George’s;-6.6
Tệp chứa một tỷ dòng (còn được gọi là hàng hoặc bản ghi). Mỗi dòng có một tên trạm theo sau là ;
thiết bị phân tách và sau đó ghi lại nhiệt độ. Số lượng trạm duy nhất có thể lên tới 10.000. Điều này ngụ ý rằng cùng một trạm xuất hiện trên nhiều dòng. Do đó, chúng tôi cần thu thập tất cả nhiệt độ cho tất cả các trạm riêng biệt trong tệp và sau đó tính toán số liệu thống kê cần thiết. Dễ dàng phải không?
Hãy bắt đầu chậm rãi nhưng đơn giản
Nỗ lực đầu tiên của tôi chỉ đơn giản là phân tích cú pháp tệp từng dòng một, sau đó thu thập kết quả vào một từ điển trong đó mỗi tên trạm là một khóa và nhiệt độ được thêm vào một vectơ của Float64
được sử dụng làm giá trị được ánh xạ tới khóa. Tôi đã mong đợi điều này sẽ diễn ra chậm, nhưng mục tiêu của chúng tôi ở đây là đạt được một con số cho hiệu suất cơ bản.
Khi từ điển đã sẵn sàng, chúng ta có thể tính toán các số liệu thống kê cần thiết:
Đầu ra của tất cả quá trình xử lý dữ liệu cần phải được hiển thị ở một định dạng nhất định. Điều này đạt được bằng chức năng sau:
Vì quá trình triển khai này dự kiến sẽ mất nhiều thời gian nên chúng tôi có thể chạy thử nghiệm đơn giản theo thời gian @time
những điều sau đây chỉ một lần:
@time get_stations_dict_v2("measurements.txt") |> calculate_output_v3 |> print_output_v1
Quá trình thực hiện của người đàn ông tội nghiệp của chúng tôi mất khoảng 526 giây, tức là ~ 9 phút. Nó chắc chắn là chậm, nhưng không tệ chút nào!
Đưa nó lên một tầm cao mới – Nhập đa luồng!
Thay vì đọc tệp đầu vào từng dòng một, chúng ta có thể thử chia nó thành các phần và sau đó xử lý tất cả các phần một cách tune tune. Julia làm cho việc thực hiện tune tune khá dễ dàng for
vòng. Tuy nhiên, chúng ta cần lấy một ít các biện pháp phòng ngừa trong khi làm như vậy.
Trước khi bắt đầu vòng lặp, trước tiên chúng ta cần tìm ra cách chia tệp thành nhiều phần. Điều này có thể đạt được bằng cách sử dụng ánh xạ bộ nhớ để đọc tập tin. Sau đó chúng ta cần xác định begin
Và finish
vị trí của từng đoạn. Điều quan trọng cần lưu ý là mỗi dòng trong tệp dữ liệu đầu vào kết thúc bằng một ký tự dòng mới, có 0x0a
dưới dạng biểu diễn byte. Vì vậy, mỗi đoạn phải kết thúc ở ký tự đó để đảm bảo rằng chúng ta không mắc bất kỳ lỗi nào khi phân tích cú pháp tệp.
Hàm sau lấy số lượng khốinum_chunks
làm đối số đầu vào, sau đó trả về một mảng với mỗi phần tử dưới dạng đoạn ánh xạ bộ nhớ.
Vì chúng tôi đang phân tích dữ liệu trạm và nhiệt độ từ các phần khác nhau nên cuối cùng chúng tôi cũng cần kết hợp chúng. Mỗi đoạn đầu tiên sẽ được xử lý thành một từ điển như được hiển thị trước đó. Sau đó, chúng tôi kết hợp tất cả các khối như sau:
Bây giờ chúng ta đã biết cách chia tệp thành các phần và cách chúng ta có thể kết hợp các từ điển được phân tích cú pháp từ các phần ở cuối. Tuy nhiên, tốc độ tăng tốc mong muốn chỉ có thể đạt được nếu chúng ta có thể xử lý các khối tune tune. Điều này có thể được thực hiện trong một for
vòng. Lưu ý rằng Julia nên bắt đầu với nhiều chủ đề julia -t 12
để giải pháp này có tác động.
Ngoài ra, bây giờ chúng tôi muốn chạy một tiêu chuẩn thống kê thích hợp. Điều này có nghĩa là thử thách phải được thực hiện một số lần nhất định và sau đó chúng ta có thể hình dung được sự phân bổ kết quả. Rất might, tất cả điều này có thể được thực hiện dễ dàng với Điểm chuẩnTools.jl. Chúng tôi giới hạn số lượng mẫu tối đa là 10, thời gian tối đa để chạy tổng cộng là 20 phút và cho phép thu gom rác (sẽ giải phóng bộ nhớ) để thực thi giữa các mẫu. Tất cả điều này có thể được tập hợp lại trong một tập lệnh duy nhất. Lưu ý rằng các đối số đầu vào bây giờ là tên của tệp fname
và số khối num_chunks.
Kết quả điểm chuẩn cùng với đầu vào được sử dụng được hiển thị bên dưới. Lưu ý rằng chúng tôi đã sử dụng 12 chủ đề ở đây.
julia> Threads.nthreads()
12julia> ARGS = ("measurements.txt", "48")
2-element Vector{String}:
"measurements.txt"
"48"
Đa luồng giúp tăng hiệu suất đáng kể, hiện chúng tôi chỉ còn khoảng hơn 2 phút. Hãy xem chúng ta có thể cải thiện điều gì khác.
Tránh lưu trữ tất cả dữ liệu nhiệt độ
Cho đến nay, cách tiếp cận của chúng tôi là lưu trữ tất cả nhiệt độ và sau đó xác định số liệu thống kê cần thiết (tối thiểu, trung bình và tối đa) ở cuối. Tuy nhiên, điều tương tự cũng có thể đạt được khi chúng tôi phân tích từng dòng từ tệp đầu vào. Chúng tôi thay thế các giá trị hiện tại mỗi khi tìm thấy một giá trị mới lớn hơn (tối đa) hoặc nhỏ hơn (tối thiểu). Để có giá trị trung bình, chúng tôi tính tổng tất cả các giá trị và giữ một bộ đếm riêng về số lần tìm thấy nhiệt độ cho một trạm nhất định.
Nhìn chung, logic mới trông giống như sau:
Chức năng kết hợp tất cả các kết quả (từ các phần khác nhau) cũng cần được cập nhật tương ứng.
Hãy chạy một điểm chuẩn mới và xem liệu thay đổi này có cải thiện thời gian hay không.
Thời gian trung bình dường như đã được cải thiện, nhưng chỉ một chút. Dù sao thì đó cũng là một chiến thắng!
Tăng cường hiệu suất hơn
Logic trước đây của chúng tôi để tính toán và lưu hỗn hợp, nhiệt độ tối đa có thể được đơn giản hóa hơn nữa. Hơn nữa, theo gợi ý từ this Bài viết của Juliachúng ta có thể sử dụng các khung nhìn (sử dụng @view
) khi phân tích tên trạm và dữ liệu nhiệt độ. Điều này cũng đã được thảo luận trong hướng dẫn thực hiện của Julia. Vì chúng ta đang sử dụng biểu thức lát cắt để phân tích từng dòng, @view
giúp chúng tôi tránh được chi phí phân bổ và sao chép.
Phần còn lại của logic vẫn giữ nguyên. Chạy điểm chuẩn bây giờ mang lại những điều sau:
Ái chà! Chúng tôi đã cố gắng đạt được gần một phút. Có vẻ như việc chuyển sang chế độ xem sẽ tạo ra sự khác biệt lớn. Có lẽ, có thể thực hiện thêm những điều chỉnh khác để cải thiện hiệu suất hơn nữa. Trong trường hợp bạn có bất kỳ đề xuất nào, hãy cho tôi biết trong phần bình luận.
Chỉ giới hạn bản thân ở căn cứ Julia thật thú vị. Tuy nhiên, trong thế giới thực, chúng ta hầu như sẽ luôn sử dụng các gói và do đó tận dụng các cách triển khai hiệu quả hiện có để thực hiện các nhiệm vụ liên quan. Trong trường hợp của chúng tôi, CSV.jl (phân tích cú pháp tệp tune tune) và DataFrames.jl (thực hiện groupby
Và mix
) sẽ có ích.
Hàm bên dưới thực hiện các tác vụ sau:
- Sử dụng
Mmap
để đọc tập tin lớn - Chia tập tin thành một số phần được xác định trước
- Lặp qua các đoạn, đọc từng đoạn tune tune bằng cách sử dụng
CSV.learn
(12 chủ đề được chuyển tớintasks
) vào DataFrame. - Sử dụng DataFrame
groupby
Vàmix
để có được kết quả cho mỗi trạm - Ghép nối tất cả các DataFrames để kết hợp các kết quả từ tất cả các khối
- Khi ở bên ngoài vòng lặp, hãy thực hiện một
groupby
Vàmix
một lần nữa để có được tập kết quả cuối cùng cho tất cả các trạm.
Bây giờ chúng ta có thể chạy điểm chuẩn theo cách tương tự như trước đây.
Hiệu suất sử dụng CSV.jl và DataFrames.jl khá tốt, mặc dù chậm hơn so với triển khai Julia cơ bản của chúng tôi. Khi làm việc trong các dự án trong thế giới thực, các gói này là một phần thiết yếu trong bộ công cụ của nhà khoa học dữ liệu. Do đó, sẽ rất thú vị nếu khám phá xem liệu có thể tối ưu hóa thêm bằng cách sử dụng phương pháp này hay không.
[ad_2]
Source link