Về hit hiệu suất (kể từ câu hỏi đầu tiên của bạn đã được trả lời đã được) - bằng mọi cách, thực hiện kiểm tra , nhưng trong các chức năng cấp cao nhất của bạn (nhận dữ liệu trực tiếp từ người dùng chức năng của bạn. Người dùng cũng có thể là một mô-đun độc lập khác, do bạn hoặc người khác viết). Không đặt các kiểm tra này trong tất cả các hàm trung gian của bạn, vì các kiểm tra đó sẽ trùng lặp và thực sự không được điều chỉnh.
EDIT
Để giải quyết vấn đề sai sót trong các chức năng trung gian, nuôi dưỡng bởi @Nasser trong các ý kiến: có một kỹ thuật rất đơn giản mà cho phép một để chuyển đổi mô hình-kiểm tra và tắt trong "một cú nhấp chuột ". Bạn có thể lưu trữ các mẫu của bạn trong các biến bên trong gói của bạn, được định nghĩa trước các định nghĩa hàm của bạn.
Dưới đây là ví dụ, trong đó f
là chức năng cấp cao nhất, trong khi g
và h
là "hàm bên trong". Chúng ta định nghĩa hai mẫu: cho hàm chính và cho những người bên trong, như vậy:
Clear[nlPatt,innerNLPatt ];
nlPatt= _?(!VectorQ[#,NumericQ]&);
innerNLPatt = nlPatt;
Bây giờ, chúng ta xác định chức năng của chúng tôi:
ClearAll[f,g,h];
f[vector:nlPatt]:=g[vector]+h[vector];
g[nv:innerNLPatt ]:=nv^2;
h[nv:innerNLPatt ]:=nv^3;
Lưu ý rằng các mô hình được thay thế trong các định nghĩa tại định nghĩa thời gian, không chạy theo thời gian, do đó, điều này hoàn toàn tương đương với việc mã hóa các mẫu đó bằng tay.Khi bạn kiểm tra, bạn chỉ cần thay đổi một dòng: từ
innerNLPatt = nlPatt
để
innerNLPatt = _
và tải lại gói của bạn.
Câu hỏi cuối cùng là - làm thế nào để bạn nhanh chóng tìm thấy lỗi? Tôi đã trả lời rằng here, trong các phần "Thay vì trả lại $Failed
, người ta có thể ném ngoại lệ, sử dụng Throw". và "Lập trình meta và tự động hóa".
END EDIT
tôi bao gồm một cuộc thảo luận ngắn gọn về vấn đề này trong cuốn sách của tôi here. Trong ví dụ đó, hiệu suất đạt được ở mức tăng 10% thời gian chạy, IMO là đường biên giới có thể chấp nhận được. Trong trường hợp ở bàn tay, việc kiểm tra đơn giản hơn và hiệu suất phạt ít hơn nhiều. Nói chung, đối với một hàm là bất kỳ phép kiểm tra loại văn bản nào được viết chính xác, chuyên sâu, chi phí chỉ chiếm một phần nhỏ trong tổng thời gian chạy.
Một vài thủ thuật mà là tốt để biết:
- Pattern-khớp có thể rất nhanh, khi được sử dụng cú pháp (không
Condition
hay PatternTest
hiện diện trong mẫu).
Ví dụ:
randomString[]:[email protected][{97,122},5];
rstest = Table[randomString[],{1000000}];
In[102]:= MatchQ[rstest,{__String}]//Timing
Out[102]= {0.047,True}
In[103]:= MatchQ[rstest,{__?StringQ}]//Timing
Out[103]= {0.234,True}
Chỉ vì trong trường hợp này các PatternTest
đã được sử dụng, việc kiểm tra là chậm hơn nhiều, vì đánh giá được gọi bởi các mô hình-khớp cho mọi phần tử, trong khi trong lần đầu tiên trường hợp, tất cả mọi thứ là hoàn toàn cú pháp và tất cả được thực hiện bên trong pattern-matcher.
- Điều này cũng đúng cho giải nén danh sách số (chênh lệch thời gian là tương tự). Tuy nhiên, đối với đóng gói danh sách số,
MatchQ
và các chức năng thử nghiệm mẫu khác không giải nén cho một số mẫu đặc biệt, hơn nữa, đối với một số mẫu, séc là tức thời.
Dưới đây là một ví dụ:
In[113]:=
test = RandomInteger[100000,1000000];
In[114]:= MatchQ[test,{__?IntegerQ}]//Timing
Out[114]= {0.203,True}
In[115]:= MatchQ[test,{__Integer}]//Timing
Out[115]= {0.,True}
In[116]:= Do[MatchQ[test,{__Integer}],{1000}]//Timing
Out[116]= {0.,Null}
Cùng, rõ ràng, có vẻ là đúng đối với các chức năng như VectorQ
, MatrixQ
và ArrayQ
với các vị từ nhất định (NumericQ
) - những thử nghiệm này là cực kỳ hiệu quả.
- Rất nhiều phụ thuộc vào cách bạn viết thử nghiệm của bạn, ví dụ: ở mức độ nào bạn sử dụng lại các cấu trúc hiệu quả Mathematica.
Ví dụ, chúng tôi muốn kiểm tra rằng chúng ta có một ma trận số thực:
In[143]:= rm = RandomInteger[10000,{1500,1500}];
Đây là cách mà hầu hết thẳng về phía trước và chậm:
In[144]:= MatrixQ[rm,NumericQ[#]&&Im[#]==0&]//Timing
Out[144]= {4.125,True}
Điều này là tốt, vì chúng tôi sử dụng lại mẫu đối sánh tốt hơn:
In[145]:= MatrixQ[rm,NumericQ]&&FreeQ[rm,Complex]//Timing
Out[145]= {0.204,True}
Chúng tôi không sử dụng bản chất đóng gói của ma trận. Điều này vẫn tốt hơn:
In[146]:= MatrixQ[rm,NumericQ]&&Total[Abs[Flatten[Im[rm]]]]==0//Timing
Out[146]= {0.047,True}
Tuy nhiên, đây không phải là kết thúc. Người sau là gần ngay lập tức:
In[147]:= MatrixQ[rm,NumericQ]&&Re[rm]==rm//Timing
Out[147]= {0.,True}
Tôi cũng đôi khi thấy mình tự hỏi về thực hiện hit của này, * + 1 * cho câu hỏi đó – Szabolcs
Tôi có nên làm cho phần biểu diễn câu hỏi như một câu hỏi riêng biệt hoặc chỉ để lại nó ở đây ? – Nasser
Tôi để nó ở đây. Tôi nhấn mạnh chúng đậm bởi vì tôi nghĩ rằng nó dễ dàng hơn nhiều để đọc và * thông báo * theo cách này. Nếu không nhiều người sẽ không bao giờ đọc được điều đó. Nếu bạn không chấp nhận câu trả lời của tôi, câu hỏi sẽ thu hút nhiều lượt xem hơn. – Szabolcs