2009-03-05 31 views
23

Tôi đang viết một trò chơi XNA, nơi tôi thực hiện kiểm tra va chạm trên mỗi pixel. Vòng lặp kiểm tra điều này làm như vậy bằng cách chuyển một int và bitwise ORing và thường khó đọc và hiểu.Tôi có thể kiểm tra xem trình biên dịch C# có nêu một lời gọi phương thức không?

Tôi muốn thêm các phương thức riêng tư như private bool IsTransparent(int pixelColorValue) để làm cho vòng lặp dễ đọc hơn, nhưng tôi không muốn chi phí cuộc gọi phương thức vì đây là mã có hiệu suất rất nhạy cảm.

Có cách nào để buộc trình biên dịch nội tuyến cuộc gọi này hoặc tôi sẽ làm tôi chỉ hy vọng rằng trình biên dịch sẽ thực hiện tối ưu hóa này?

Nếu không có cách nào để ép buộc điều này, có cách nào để kiểm tra xem phương pháp đã được gạch chân hay chưa, có đọc được cách tháo gỡ không? Liệu phương pháp sẽ hiển thị trong sự phản ánh nếu nó được inlined và không có người gọi khác tồn tại?

Chỉnh sửa: Tôi không thể ép buộc, vì vậy tôi có thể phát hiện không?

+1

Bạn có thể (trong .Net 4.5). sử dụng: '[MethodImpl (MethodImplOptions.AggressiveInlining)]' – Mahmoodvcs

Trả lời

23

Không bạn không thể. Thậm chí nhiều hơn, một trong những người quyết định inlining không phải là trình biên dịch VS mà sẽ đưa bạn mã và chuyển đổi nó thành IL, nhưng trình biên dịch JIT mà mất IL và chuyển đổi nó thành mã máy. Điều này là do chỉ có trình biên dịch JIT biết đủ về kiến ​​trúc bộ vi xử lý để quyết định nếu đặt một phương thức nội tuyến là thích hợp vì nó là sự cân bằng giữa hướng dẫn pipelining và kích thước bộ nhớ cache.

Vì vậy, ngay cả khi tìm trong .NET Reflector cũng sẽ không giúp bạn.

+0

Những người khác cầu xin sự khác biệt về sự phản chiếu vì nó sử dụng ngăn xếp cuộc gọi. http://stackoverflow.com/questions/44153/can-you-use-reflection-to-find-the-name-of-the-currently-executing-method/44171#44171 –

+1

Tôi không nói sự phản chiếu, tôi cho biết phản xạ, như trong Red Gates .NET Reflector. –

+0

Tệ của tôi, tôi hiểu lầm điều đó. –

1

Không, bạn không thể.

Về cơ bản, bạn không thể làm điều đó trong hầu hết các trình biên dịch C++ hiện đại. inline chỉ là một đề nghị cho trình biên dịch. Hoàn toàn miễn phí để lấy nó hay không.

Trình biên dịch C# không thực hiện bất kỳ nội tuyến đặc biệt nào ở cấp IL. Trình tối ưu hóa JIT là trình tối ưu hóa sẽ làm điều đó.

+0

"Nếu không có một cách để buộc điều này, là có một cách để kiểm tra xem phương pháp đã được inlined, ngắn đọc các disassembly? Sẽ phương pháp hiển thị trong phản ánh nếu nó được gạch chân và không có người gọi nào khác tồn tại? " –

+0

Không, tôi nghi ngờ trình biên dịch C# thực hiện bất kỳ nội tuyến nào cả. Trình biên dịch JIT chịu trách nhiệm cho điều đó. –

+0

Bạn có thể kiểm tra System.Reflection.MethodBase.GetCurrentMethod(). Nếu phương thức được gạch chân, nó sẽ trả về tên của người gọi thay thế. –

14

"Bạn có thể kiểm tra System.Reflection.MethodBase.GetCurrentMethod(). Tên. Nếu phương pháp này được sắp xếp theo hàng nó sẽ trả lại tên của người gọi để thay thế."

- Joel Coehoorn

+0

Nó sẽ chỉ hoạt động khi chạy. –

+19

Tất nhiên nó sẽ chỉ hoạt động trong thời gian chạy, đó là khi nội tuyến xảy ra. –

+10

Không gọi phương pháp này trong mã của bạn thay đổi IL thực tế, mà về mặt lý thuyết sẽ thay đổi 'lý luận' của trình biên dịch JIT nếu nó được inline hay không? –

0

Bạn có thể phát hiện nó trong thời gian chạy bằng cuộc gọi GetCurrentMethod nói trên. Nhưng, có vẻ như là một chút lãng phí [1]. Điều dễ nhất để làm chỉ là ILDASM MSIL và kiểm tra ở đó.

Lưu ý rằng điều này dành riêng cho trình biên dịch nội tuyến cuộc gọi và được bao gồm trong các tài liệu Reflection khác nhau trên MSDN.

Nếu phương thức gọi phương thức GetCallingAssembly được mở rộng nội bộ bởi trình biên dịch (nghĩa là, nếu trình biên dịch chèn phần thân hàm vào ngôn ngữ trung gian Microsoft phát ra, thay vì phát ra một cuộc gọi hàm), thì assembly được trả về bởi phương thức GetCallingAssembly là assembly chứa mã nội tuyến. Điều này có thể khác với assembly có chứa phương thức gốc. Để đảm bảo rằng một phương thức gọi phương thức GetCallingAssembly không được biên dịch bởi trình biên dịch, bạn có thể áp dụng thuộc tính MethodImplAttribute với MethodImplOptions.NoInlining.

Tuy nhiên, JITter cũng miễn phí gọi nội tuyến - nhưng tôi nghĩ rằng trình tách rời sẽ là cách duy nhất để xác minh những gì và không được thực hiện ở cấp đó.

Chỉnh sửa: Chỉ cần xóa một số nhầm lẫn trong chuỗi này, csc.exe will inline MSIL calls - mặc dù JITter (có thể) tích cực hơn trong đó.

[1] Và, do lãng phí - ý tôi là (a) nó đánh bại mục đích của nội tuyến (hiệu suất tốt hơn) vì tra cứu phản ánh. Và (b), nó có lẽ sẽ thay đổi hành vi nội tuyến để nó không còn được gạch chân nữa. Và, trước khi bạn nghĩ rằng bạn chỉ có thể biến nó trên Debug xây dựng với một Assert hoặc một cái gì đó - nhận ra rằng nó sẽ không được inlined trong Debug, nhưng có thể được phát hành.

+0

Yep: chắc chắn là một sự lãng phí để kiểm tra điều này khi chạy. Nếu nó đã được JIT'd nội tuyến, có lẽ có một lý do _good_ cho nó, và kiểm tra này sẽ chỉ làm cho mọi việc tồi tệ hơn. Nhưng tôi đã thực hiện điều này như một bài tập học tập nhiều hơn: anh ấy muốn "trải nghiệm" nội tuyến cho bản thân mình. –

1

tại sao không sử dụng mã không an toàn (inline c như đã biết) và sử dụng con trỏ kiểu c/C++, điều này an toàn từ GC (nghĩa là không bị ảnh hưởng bởi bộ sưu tập). các ứng dụng vùng internet) nhưng là tuyệt vời cho các loại điều nó xuất hiện bạn đang cố gắng để đạt được đặc biệt là với hiệu suất và thậm chí nhiều hơn như vậy với mảng và hoạt động bitwise?

để tóm tắt, bạn muốn hiệu suất cho một phần nhỏ ứng dụng của mình? sử dụng mã không an toàn và sử dụng con trỏ vv có vẻ là tùy chọn tốt nhất cho tôi

CHỈNH SỬA: một chút khởi động? http://msdn.microsoft.com/en-us/library/aa288474(VS.71).aspx

+4

mã không an toàn thường chậm hơn mã được quản lý, vì JIT không thể đảm bảo nhiều về mã của bạn nên không thể thực hiện tối ưu hóa nhất định. Vì vậy, nếu bạn làm điều này, như mọi khi, ** hồ sơ! ** –

0

Có cách nào để buộc trình biên dịch thực hiện cuộc gọi này hoặc tôi có hy vọng rằng trình biên dịch sẽ thực hiện tối ưu hóa này không?

Nếu nó rẻ hơn để nội tuyến chức năng, nó sẽ. Vì vậy, đừng lo lắng về nó trừ khi profiler của bạn nói rằng nó thực sự là một vấn đề.

Để biết thêm thông tin

JIT Enhancements in .NET 3.5 SP1

4

Hãy nhận biết rằng Xbox làm việc khác nhau.

Một google bật lên này:

"Phương pháp nội tuyến mà giảm nhẹ chi phí của một cuộc gọi của một phương pháp hình thức JIT vào một inline gì đáp ứng các điều kiện sau

  • Mã IL.. kích thước là 16 byte hoặc ít hơn.
  • lệnh chi nhánh không được sử dụng (nếu câu vv).
  • biến địa phương không được sử dụng.
  • Xử lý ngoại lệ không được thực hiện (thử, bắt, v.v.).
  • phao không được sử dụng làm đối số hoặc giá trị trả lại của phương thức (có thể là Xbox 360, không được áp dụng).
  • Khi hai hoặc nhiều đối số nằm trong phương thức , nó sử dụng cho lần lượt được khai báo.

Tuy nhiên, chức năng ảo không được tạo thành nội dòng."

http://xnafever.blogspot.com/2008/07/inline-method-by-xna-on-xbox360.html

Tôi không có ý tưởng nếu ông là đúng. Bất cứ ai?

+0

Cảm ơn bạn đã chỉ ra điều này. Nó thực sự khá phù hợp với tôi. Sẽ được tốt đẹp để xem nó trong một tài liệu chính thức mặc dù. –

1

Cách duy nhất để kiểm tra này là để có được hoặc viết một hồ sơ, và móc vào các sự kiện JIT, bạn cũng phải làm chắc chắn nội tuyến không bị tắt vì nó là theo mặc định khi profiling

14

có một cách mới để khuyến khích nhiều nội tuyến agressive trong .net 4.5 được mô tả ở đây:. http://blogs.microsoft.co.il/blogs/sasha/archive/2012/01/20/aggressive-inlining-in-the-clr-4-5-jit.aspx

Về cơ bản nó chỉ là một lá cờ để te sẽ trình biên dịch nội tuyến nếu có thể. Thật không may, nó không có sẵn trong phiên bản hiện tại của XNA (Game Studio 4.0) nhưng sẽ có sẵn khi XNA bắt kịp VS 2012 năm nay một thời gian. Nó đã có sẵn nếu bạn bằng cách nào đó đang chạy trên Mono.

[MethodImpl(MethodImplOptions.AggressiveInlining)] 
public static int LargeMethod(int i, int j) 
{ 
    if (i + 14 > j) 
    { 
     return i + j; 
    } 
    else if (j * 12 < i) 
    { 
     return 42 + i - j * 7; 
    } 
    else 
    { 
     return i % 14 - j; 
    } 
} 
Các vấn đề liên quan