2010-05-28 33 views
5

Tôi đang mã hóa bản sao đột phá. Tôi đã có một phiên bản mà tôi chỉ có một cấp độ sâu của cấu trúc. Phiên bản này chạy ở tốc độ 70 khung hình/giây.C: sử dụng rất nhiều cấu trúc có thể làm chậm chương trình?

Để rõ ràng hơn trong mã, tôi đã quyết định mã nên có nhiều trừu tượng hơn và tạo nhiều cấu trúc hơn. Hầu hết thời gian tôi có hai hai cấp độ sâu của cấu trúc. Phiên bản này chạy ở tốc độ 30 khung hình/giây.

Vì có một số khác biệt khác ngoài cấu trúc, tôi hỏi bạn: Việc sử dụng rất nhiều cấu trúc trong C có thể làm chậm mã đáng kể không?

Ví dụ trên phiên bản thứ hai, tôi đang sử dụng:

struct Breakout 
{ 
    Ball ball; 
    Paddle paddle; 
    Level* levels; 
} 

struct Level 
{ 
    Bricks* bricks; 
} 

Vì vậy, tôi đang sử dụng rất nhiều lần breakout.levels [level_in_play] .bricks [i] .visible ví dụ. Đây có phải là nguyên nhân có thể không?

Cảm ơn.

+0

Các cấu trúc "sâu" vì giá trị hoặc tham chiếu? Bạn đang thực hiện phân bổ bộ nhớ động? – WhirlWind

+0

Tôi đang sử dụng mallocs có. – nunos

+1

Nếu bạn đang phân bổ động bộ nhớ trong một con đường nhạy cảm với hiệu năng, điều đó chắc chắn có thể làm chậm mọi thứ; Tôi muốn chạy một hồ sơ nhanh chóng trên hai phiên bản mã của bạn để xem lý do tại sao, mặc dù. Bạn cần hiển thị một chút mã, không chỉ một số cấu trúc dữ liệu. – WhirlWind

Trả lời

11

Thực hiện nhiều điều kiện trỏ chuột có thể là một lần truy cập hiệu suất. Khi bạn chia một struct lớn lên vào cấu trúc nhỏ hơn, có hai điều xảy ra:

  1. Truy cập vào một thành viên của một phụ struct đòi hỏi một dereference thêm con trỏ và bộ nhớ lấy, đó là hơi chậm hơn, và
  2. Bạn có thể giảm các locality of reference, gây ra nhiều bộ nhớ cache và lỗi trang và có thể làm giảm đáng kể hiệu suất.

Địa điểm tham chiếu có thể là những gì đang cắn bạn ở đây. Nếu có thể, hãy cố gắng phân bổ các cấu trúc liên quan trong cùng một khối malloc, làm tăng khả năng chúng sẽ được lưu trữ cùng nhau.

+0

Thêm vào một số hồ sơ, và đây là điểm trên. –

+0

Bạn đã bao giờ thực sự tìm thấy sự dereference của một con trỏ là nguyên nhân của một vấn đề hiệu suất? Chắc chắn nó sẽ gây ra một số lượng nhỏ, gần như infinitesimal số lượng công việc phụ, nhưng tôi không nghĩ rằng dereferencing con trỏ sẽ bao giờ trở thành một vấn đề, trừ khi bạn đang thực hiện nó một lần gazillion cho mỗi hoạt động khác. Profiling sẽ là cách duy nhất để tránh bi quan sớm. – Allbite

+0

@ Allbite: Rõ ràng là tôi chưa đủ rõ ràng. Nó không phải là suy nghĩ có thể gây ra hiệu suất (ít nhất, không có khả năng - tôi chắc chắn có những trường hợp cạnh mà nó quan trọng), đó là thực tế rằng bạn đang có khả năng đưa các phần liên quan chặt chẽ của dữ liệu ở những nơi khác nhau trong bộ nhớ . Tất nhiên việc lược tả ứng dụng là quan trọng, nhưng vấn đề tham chiếu địa phương có thể khó phát hiện với một trình chạy hồ sơ, vì hồ sơ đã ảnh hưởng đến hiệu suất và địa phương tham chiếu chỉ bằng cách đính kèm. –

4

Ở nơi đầu tiên, thật dễ dàng và hấp dẫn để đoán vấn đề là gì. Điều lén lút về dự đoán là - đôi khi chúng đúng. Nhưng tại sao đoán, khi bạn có thể tìm ra cho thả chết chắc chắn những gì đang dành thời gian. I recommend this approach.

Điều đó nói rằng, đây là phỏng đoán của tôi. mallocfree, nếu bạn từng bước qua chúng ở cấp độ ngôn ngữ lắp ráp, có thể làm nhiều hơn bạn tưởng. Tôi chỉ cấp phát bộ nhớ cho các cấu trúc nếu tôi biết tôi sẽ không làm việc đó ở tần số đặc biệt cao. Nếu tôi phải phân bổ/deallocate chúng động, ở tần số cao, nó giúp để có một danh sách miễn phí của bản sao được sử dụng, vì vậy tôi chỉ có thể lấy chúng ra khỏi danh sách thay vì đi đến malloc tất cả các thời gian.

Tuy nhiên, hãy chụp một số ảnh chụp nhanh. Rất có thể bạn có thể khắc phục một loạt sự cố và làm cho toàn bộ lô hàng toàn bộ số nhanh hơn.

4

Việc thêm các lớp hội nghị dereferencing bổ sung có thể gây ra một lượng nhỏ (rất ít) chi phí làm chậm. Lý do là, mỗi -> mà trình biên dịch thấy có nghĩa là nó phải làm một tra cứu bộ nhớ bổ sung và bù đắp. Ví dụ, c->b->a yêu cầu trình biên dịch tải con trỏ c vào bộ nhớ, tham khảo nó, bù đắp cho b, dereference đó, bù đắp cho một, dereference đó, sau đó tải một bộ nhớ vào. Đó là khá nhiều công việc bộ nhớ. Làm c.b.a yêu cầu tải ban đầu của c, một lần thêm, sau đó tải trực tiếp từ bộ nhớ. Đó là 2 tải so với 5.

Trừ khi loại công việc này đang được thực hiện một tấn trong các vòng nhỏ, chặt chẽ, nó sẽ không phải trả tiền để ngồi xổm theo thời gian.Nếu bạn đang làm điều này trong vòng bên trong nặng nề mặc dù (và trình biên dịch của bạn không giúp bạn), sau đó nó có thể tăng lên. Đối với những trường hợp đó, hãy xem xét lưu vào bộ nhớ đệm con trỏ cấu trúc cấp thấp nhất và làm việc từ đó.

Điều đó nói rằng, bất cứ khi nào bạn khởi động hiệu suất, bước một là hồ sơ. Nếu không có một hồ sơ, bạn đang đoán. Bạn đã thực hiện một khẳng định rằng cấu trúc derefencing là gốc của hiệu suất của bạn, nhưng không có một cập nhật và hồ sơ hợp lệ (trên một bản phát hành xây dựng) bạn đang đoán và có lẽ lãng phí thời gian.

+0

+1 - Theo kinh nghiệm của tôi, điều này khó xảy ra mặc dù các cấu trúc đang gây ra sự chậm lại lớn. Hồ sơ. –

1

Không phải "rất nhiều cấu trúc" trong chính nó, khác với tiềm năng cho số lượng bộ nhớ truy cập lớn hơn. "rất nhiều sự vô hướng" tuy nhiên có nhiều khả năng là một nguyên nhân. Bạn phải xem xét có bao nhiêu truy cập bộ nhớ được tạo ra để có được dữ liệu thực tế. Khoảng cách và kích thước dữ liệu cũng có thể ảnh hưởng đến bộ nhớ đệm, nhưng khó phân tích hơn.

Cũng vì bạn đã đề cập trong một nhận xét rằng bạn đang thực hiện phân bổ bộ nhớ động, thời gian thực hiện để tìm phân bổ một khối là không xác định và biến. Nếu bạn liên tục phân bổ và giải phóng các khối trong khi thực thi thuật toán (thay vì phân bổ trước khi khởi tạo ví dụ), điều này có thể gây ra cả sự suy giảm và biến đổi về hiệu suất.

Nếu bạn có công cụ lược tả, hãy lập cấu hình mã để biết vị trí xảy ra lần truy cập.

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