2013-04-21 17 views
6

Tôi đang viết một số mã toán học trong C#, buộc nó biên dịch cho x86 trong bản phát hành, tối ưu hóa và tôi đang xem xét việc tháo gỡ trong windbg. Nó thường khá tốt, thường viết tốt hơn so với tôi có thể (không phải là tôi là tất cả tốt tại hội đồng, nhưng có bạn đi).Math.Atan2 và FPATAN

Tuy nhiên, tôi đã nhận thấy rằng chức năng này:

static void TemporaryWork() 
{ 
    double x = 4; 
    double y = 3; 
    double z = Math.Atan2(x, y); 
} 

Được sản xuất tháo gỡ này:

001f0078 55    push ebp 
001f0079 8bec   mov  ebp,esp 
001f007b dd05a0001f00 fld  qword ptr ds:[1F00A0h] 
001f0081 83ec08   sub  esp,8 
001f0084 dd1c24   fstp qword ptr [esp] 
001f0087 dd05a8001f00 fld  qword ptr ds:[1F00A8h] 
001f008d 83ec08   sub  esp,8 
001f0090 dd1c24   fstp qword ptr [esp] 
001f0093 e86e9ba66f  call clr!GetHashFromBlob+0x94e09 (6fc59c06) (System.Math.Atan2(Double, Double), mdToken: 06000de7) 
001f0098 ddd8   fstp st(0) 
001f009a 5d    pop  ebp 
001f009b c3    ret 

Thậm chí nếu bạn không phải là một guru x86, bạn sẽ nhận thấy một cái gì đó kỳ lạ trong ở đó: có một cuộc gọi tới System.Math.Atan2. Như trong một cuộc gọi hàm.

Nhưng có thực sự là một x86 opcode rằng sẽ làm điều đó: FPATAN

Tại sao JITer gọi một chức năng khi có một hướng dẫn lắp ráp thực tế để làm các hoạt động? Tôi nghĩ rằng System.Math về cơ bản là một wrapper cho hướng dẫn lắp ráp bản địa. Hầu hết các hoạt động trong đó có opcodes lắp ráp trực tiếp. Nhưng đó rõ ràng không phải là trường hợp?

Có ai có bất kỳ thông tin nào về lý do khiến JITer không/không thể thực hiện tối ưu hóa khá rõ ràng này không?

+1

Nếu tôi google 'lỗi trong fpatan' tôi nhận được một số kết quả cho nó cho một số mô hình xử lý, do đó, nó có thể là' Math.Atan2' hoạt động xung quanh các lỗi này và là một thay thế cho nó trong 'Math.Atan'. Tôi không thực sự chắc chắn nhưng có lẽ nó có thể là hướng để tìm kiếm? Câu hỏi hay. – Silvermind

+0

"Có ai có bất kỳ thông tin nào về lý do tại sao JITer không/không thể thực hiện tối ưu hóa rõ ràng này không?" Tôi sẽ không giả vờ nói cho JIT đang nghi vấn, nhưng là người đã triển khai 'atan2' cho nhiều nền tảng FPATAN chậm hơn nhiều so với việc triển khai phần mềm tốt, thậm chí bao gồm cả phí gọi hàm (150-300 chu kỳ so với 50-100 chu kỳ, tùy thuộc vào thư viện và phần cứng cụ thể trong –

Trả lời

5

Bạn có thể theo dõi lý do từ this answer, nó cho biết cách các hàm toán học này được ánh xạ bởi jitter.

Điều này sẽ đưa bạn đến hàm clr/src/classlibnative/float/comfloat.cpp, ComDouble :: Atan2(). Điều này giải thích lý do:

// the intrinsic for Atan2 does not produce Nan for Atan2(+-inf,+-inf) 
    if (IS_DBL_INFINITY(x) && IS_DBL_INFINITY(y)) { 
     return(x/y);  // create a NaN 
    } 
    return (double) atan2(x, y); 

Vì vậy, giải pháp khắc phục hành vi FPU không tuân thủ CLI.

+0

Tôi sẽ không nói bất cứ điều gì đang được cố định ở đây.Nó là một bộ chuyển đổi chứ không phải là một fixer –

+0

Ah mát mẻ, nhưng sau nguồn tôi không nghĩ đó là nhất thiết phải là lý do.Có vẻ như có rất nhiều chức năng không được ánh xạ tới bản chất, nhưng chúng không làm bất cứ điều gì thêm.Ví dụ, COMDouble :: Log theo nghĩa đen chỉ gọi các bản ghi nội tại từ ecall.cpp, chỉ có sin, cos, sqrt, round, và abs đang được ánh xạ trực tiếp thành nội tại. –

+0

Bạn có thể xem mã cho ComDouble :: Exp and Log, một lần nữa với một chú thích. Nó lưu ý rằng phiên bản SSE2 của chúng quá chậm và Exp có một vấn đề miền tương tự. Họ không ** sử dụng một intrisic, nó gọi các phiên bản CRT của các chức năng này. Mã lắp ráp thủ công từ Intel. Nếu bạn có một lý thuyết tốt hơn so với các nhận xét khá rõ ràng thì chúng tôi rất muốn nghe nó. –

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