5

vấn đề đầu tiênHai vấn đề hiệu quả lạ trong Mathematica

Tôi đã timed phải mất bao lâu để tính toán những điều khoản sau đây (trong đó V [x] là một thời gian chuyên sâu gọi hàm):

Alice  = Table[V[i],{i,1,300},{1000}]; 
Bob  = Table[Table[V[i],{i,1,300}],{1000}]^tr; 
Chris_pre = Table[V[i],{i,1,300}]; 
Chris  = Table[Chris_pre,{1000}]^tr; 

Alice , Bob và Chris là các ma trận giống hệt nhau tính 3 cách hơi khác nhau. Tôi thấy rằng Chris được tính nhanh gấp 1000 lần so với Alice và Bob. Không có gì ngạc nhiên khi Alice được tính chậm hơn 1000 lần bởi vì, ngây thơ, hàm V phải được gọi là 1000 lần nhiều hơn khi Chris được tính toán. Nhưng điều đáng ngạc nhiên là Bob chậm quá, vì anh ta được tính giống hệt nhau đối với Chris ngoại trừ việc Chris lưu trữ bước trung gian Chris_pre.

Tại sao Bob đánh giá quá chậm?


THỨ HAI VẤN ĐỀ

Giả sử tôi muốn biên dịch một hàm trong Mathematica có dạng

f(x)=x+y 

nơi "y" là một hằng số cố định tại thời gian biên dịch (nhưng mà tôi không muốn trực tiếp thay thế trong mã bằng số của nó bởi vì tôi muốn có thể dễ dàng thay đổi nó). Nếu giá trị thực tế của y là y = 7.3 và tôi xác định

f1=Compile[{x},x+y] 
f2=Compile[{x},x+7.3] 

thì f1 chạy chậm hơn 50% so với f2. Làm thế nào để làm cho Mathematica thay thế "y" bằng "7.3" khi f1 được biên dịch, do đó f1 chạy nhanh như f2?


EDIT:

Tôi tìm thấy một workaround xấu xí cho vấn đề thứ hai:

f1=ReleaseHold[Hold[Compile[{x},x+z]]/.{z->y}] 

Có phải là một cách tốt hơn ...

Trả lời

5

Bạn có lẽ nên đã đăng những như những câu hỏi riêng biệt, nhưng không phải lo lắng!

Vấn đề một

Vấn đề với Alice dĩ nhiên là điều bạn mong đợi. Vấn đề với Bob là bên trong Table được đánh giá một lần cho mỗi lần lặp lại của bên ngoài Table. Điều này hiển thị rõ ràng với Trace:

Trace[Table[Table[i, {i, 1, 3}], {3}]] 

{ 
Table[Table[i,{i,1,2}],{2}], 
{Table[i,{i,1,2}],{i,1},{i,2},{1,2}},{Table[i,{i,1,2}],{i,1},{i,2},{1,2}}, 
{{1,2},{1,2}} 
} 

Dấu ngắt dòng được thêm vào để nhấn mạnh, và đầu ra của Trace on Table hơi lạ, nhưng bạn có thể thấy nó. Rõ ràng Mathematica có thể tối ưu hóa điều này tốt hơn, biết rằng bảng bên ngoài không có trình lặp, nhưng vì lý do gì, nó không tính đến điều đó. Chỉ Chris thực hiện những gì bạn muốn, mặc dù bạn có thể sửa đổi Bob:

Transpose[Table[Evaluate[Table[V[i],{i,1,300}]],{1000}]] 

Có vẻ như nó thực sự tốt hơn Chris với hệ số hai hoặc hơn, vì nó không phải lưu trữ kết quả trung gian.

Vấn đề hai

Có một giải pháp đơn giản hơn với Đánh giá, mặc dù tôi hy vọng nó sẽ không làm việc với tất cả các chức năng có thể được biên dịch (tức là những người thực sự cần được tổ chức):

f1 = Compile[{x}, Evaluate[x + y]]; 

Bạn cũng có thể sử dụng một With:

With[{y=7.3}, 
    f1 = Compile[{x}, x + y]; 
] 

Hoặc nếu y được xác định ở nơi khác, sử dụng tạm thời:

y = 7.3; 
With[{z = y}, 
    f1 = Compile[{x}, x + z]; 
] 

Tôi không phải là chuyên gia về các cơ chế đánh giá và đánh giá của Mathematica, do đó có thể dễ dàng hơn, nhưng hy vọng một trong số đó sẽ giúp bạn!

+0

Wow, cảm ơn rất nhiều! Điều này thật đúng với gì mà tôi đã tìm kiếm. (Và tôi sẽ đảm bảo đăng các sự cố như thế này một cách riêng biệt trong tương lai.) –

+0

Sử dụng 'With' có lẽ là cách an toàn nhất để giải quyết vấn đề hai, vì nó thực sự thay thế từ vựng trước bất kỳ đánh giá nào của cơ thể. –

+0

@Michael Pilat: Đồng ý. Tôi đề nghị Đánh giá theo tinh thần của một cách tiếp cận nhanh chóng và bẩn nếu bạn đã xác định 'y', nhưng biến phụ tạm thời chắc chắn an toàn hơn. – Cascabel

1

Vấn đề đầu tiên Bạn đã kiểm tra đầu ra của tính toán Chris_pre chưa? Bạn sẽ thấy rằng nó không phải là một ma trận lớn ở tất cả, vì bạn đang cố gắng để lưu trữ một kết quả trung gian trong một mô hình, chứ không phải là một biến. Hãy thử ChrisPre, thay vào đó. Sau đó tất cả các timings được so sánh.

Vấn đề thứ hai Biên dịch có một số hạn chế khó khăn khi sử dụng. Một vấn đề là bạn không thể tham chiếu đến các biến toàn cục. The Với cấu trúc đã được đề xuất là cách được đề xuất xung quanh điều này. Nếu bạn muốn tìm hiểu thêm về Compile, hãy kiểm tra thủ đoạn Ted Ersek của: http://www.verbeia.com/mathematica/tips/Tricks.html

+0

Rất tiếc. Trong mã thực tế của tôi, tôi đã sử dụng Chris1 là một tên biến có thể chấp nhận được. Tôi đã quên khi viết điều này mà không thể sử dụng dấu gạch dưới cho các biến trong Mathematica. Cảm ơn rất nhiều về liên kết. Điều này trông giống như một số công cụ tốt. –

2

vấn đề đầu tiên của bạn đã được giải thích, nhưng tôi muốn chỉ ra rằng ConstantArray được giới thiệu vào Mathematica 6 để giải quyết vấn đề này. Trước thời điểm đó, Table[expr, {50}] được sử dụng cho cả biểu thức cố định và thay đổi.

Kể từ khi giới thiệu ConstantArray có sự tách biệt rõ ràng giữa lần lặp lại với đánh giá lại và sao chép đơn giản của một biểu thức. Bạn có thể thấy các hành vi sử dụng này:

ConstantArray[Table[Pause[1]; i, {i, 5}], {50}] ~Monitor~ i 

Phải mất năm giây để lặp qua TablePause[1], nhưng sau khi vòng lặp đó là hoàn toàn nó không được đánh giá lại và 50 bản sao được in ngay lập tức.

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