2015-04-30 23 views
10

Tôi đang xử lý một số tập dữ liệu lớn và đang làm những gì tôi có thể để ở trong giới hạn bộ nhớ của R. Một câu hỏi xuất hiện liên quan đến việc ghi đè các đối tượng R. Tôi có một lớn data.table (hoặc bất kỳ đối tượng R), và nó phải được sao chép vào tmp nhiều lần. Câu hỏi đặt ra là: nó có tạo nên sự khác biệt nào nếu tôi xóa tmp trước khi ghi đè lên nó? Trong mã:Bộ nhớ được quản lý như thế nào khi ghi đè các đối tượng R?

for (1:lots_of_times) { 
    v_l_d_t_tmp <- copy(very_large_data_table) # Necessary copy of 7GB data 
               # table on 16GB machine. I can 
               # afford 2 but not 3 copies. 
    ### do stuff to v_l_d_t_tmp and output 
    rm (v_l_d_t_tmp) # The question is whether this rm keeps max memory 
         # usage lower, or if it is equivalent to what an 
         # overwrite will automatically do on the next iteration. 
} 

Giả sử bản là cần thiết (Nếu tôi đạt được một điểm mà tôi cần phải đọc very_large_data_table từ đĩa ở mỗi vòng lặp, tôi sẽ làm điều đó, nhưng câu hỏi đứng: nó sẽ làm cho bất kỳ sự khác biệt về tối đa sử dụng bộ nhớ nếu tôi xóa một cách rõ ràng v_l_d_t_tmp trước khi tải lại vào nó?).

Hoặc, để dạy cho người đàn ông câu cá, tôi có thể gõ gì (trong R, chúng ta không thể vào được ps) để tự mình trả lời?

Hoàn toàn OK nếu câu trả lời hóa ra là: "Tin tưởng thu gom rác thải".

+0

Không phải chuyên gia, nhưng nó không tạo nên sự khác biệt. Trong cả hai trường hợp, vị trí bộ nhớ ban đầu không còn được chỉ định bởi một biểu tượng, vì vậy đủ điều kiện để thu thập rác (vui lòng được các chuyên gia sửa chữa). Một điều cần xem xét là liệu 'data.table' của bạn có thực sự cần được sao chép hay không. Nó được thiết kế để được sửa đổi bằng cách tham chiếu, do đó bạn không phải làm điều đó. – BrodieG

+2

Khi @BrodieG cho biết sử dụng 'rm' cho' R' rằng bạn không còn cần phải truy cập 'v_l_d_t_tmp' và bộ nhớ bị chiếm bởi bảng này sẽ đủ điều kiện để thu thập rác. Tuy nhiên việc thu gom rác thải không diễn ra khi bạn gọi 'rm', nhưng" tự động ", khi cần. Điều này không phải lúc nào cũng hoạt động tốt, vì vậy bạn có thể ép buộc thu gom rác bằng cách gọi 'gc()' ngay sau khi bạn gọi 'rm (...)'. Điều này có thể làm cho vòng lặp của bạn hoạt động. Tuy nhiên trong kinh nghiệm của tôi, bạn thực sự cần phải khởi động lại R cho bộ nhớ được xóa sạch (có nghĩa là đọc trong đầu vào của bạn cho mỗi lần lặp lại, có lẽ khá chậm). – konvas

+0

Từ kinh nghiệm của riêng tôi - người thu gom rác tin cậy. Chúng tôi đã phân tích cú pháp dữ liệu di truyền và chúng tôi đã ghi đè tất cả các khung dữ liệu bằng các dữ liệu mới, nhưng tôi không có nền tảng lý thuyết hỗ trợ ... –

Trả lời

1

Đây là nhận xét không chỉ là câu trả lời mà còn quá dài.

Tôi đoán rằng trong trường hợp này, cuộc gọi tới rm có thể là chính xác. Tôi nghĩ rằng bắt đầu từ lần lặp thứ hai, bạn có thể có 3 bảng trong bộ nhớ nếu bạn không gọi rm. Trong khi sao chép đối tượng lớn, R không thể giải phóng bộ nhớ bị chiếm bởi v_l_d_t_tmp trước khi kết thúc bản sao, vì cuộc gọi hàm có thể có lỗi và trong trường hợp này, đối tượng cũ phải được giữ nguyên. Hãy xem xét ví dụ này:

x<-1:10 
myfunc<-function(y) {Sys.sleep(3);30} 

Ở đây tôi đã xác định đối tượng và hàm cần một thời gian để làm điều gì đó. Nếu bạn cố gắng:

x<-myfunc() 

và phá vỡ thực hiện trước khi nó kết thúc "một cách tự nhiên", đối tượng x vẫn còn tồn tại, với nội dung 1:10 của nó. Vì vậy, tôi đoán rằng trong trường hợp của bạn, ngay cả khi bạn sử dụng cùng một biểu tượng, R không thể giải phóng nội dung của nó trước hoặc trong bản sao. Nó có thể nếu bạn loại bỏ nó trước bản sao sau. Tất nhiên, đối tượng sẽ bị xóa sau khi sao chép, nhưng bạn có thể hết bộ nhớ trong đó.

Tôi không phải là một chuyên gia về R internals, vì vậy đừng coi thường những gì tôi vừa nói.

2

Đây là một ý tưởng khác ... nó không trực tiếp trả lời câu hỏi của bạn, thay vào đó hãy cố gắng giải quyết nó bằng cách loại bỏ vấn đề bộ nhớ theo cách khác. Có thể khiến bạn suy nghĩ:

Điều gì sẽ xảy ra nếu bạn thay thế bộ nhớ cache very_large_data_table, sau đó đọc nó chỉ một lần, làm những gì bạn cần làm rồi thoát R. Bây giờ, viết vòng bên ngoài R và vấn đề bộ nhớ biến mất. Cấp, điều này chi phí bạn CPU nhiều hơn bởi vì bạn phải đọc trong 7GB nhiều lần ... nhưng nó có thể là giá trị tiết kiệm chi phí bộ nhớ. Trong thực tế, điều này giảm một nửa sử dụng bộ nhớ của bạn, vì bạn không cần phải sao chép bảng.

Ngoài ra, như @konvas chỉ ra trong các nhận xét, tôi cũng thấy rằng rm() thậm chí với gc() không bao giờ có được những gì tôi cần với một vòng lặp dài, bộ nhớ sẽ tích lũy và cuối cùng bị hỏng. Thoát R là cách dễ dàng.

tôi phải làm điều này thường xuyên đến nỗi tôi đã viết một gói để giúp tôi đối tượng Cache như thế này: simpleCache

nếu bạn muốn thử, nó sẽ giống như thế này:

làm điều này bên ngoài của R:

for (1:lots_of_times) { 
Rscript my_script.R 
} 

Sau đó, trong R, làm được điều này ... my_script.R:

library(simpleCache) 
simpleCache("very_large_data_table", {r code for how 
you make this table }, assignTo="v_l_d_t_tmp") 

### do stuff to v_l_d_t_tmp and output 
+0

Đây không phải là tin tuyệt vời cho R nếu đây là câu trả lời đúng. simpleCache trông rất tuyệt, cảm ơn. – enfascination

Các vấn đề liên quan