2012-12-11 5 views
6

Tôi đang viết một trò chơi trong Android/OpenGL và đang cố gắng tách logic OpenGL (render) khỏi logic cập nhật trò chơi của mình, bằng cách chạy từng chủ đề riêng để cải thiện hiệu suất.Android: Chủ đề không chạy song song

tôi quản lý để nhận được mỗi chạy trên thread riêng của mình, tuy nhiên theo Tracer trong DDMS, các chủ đề vẫn đang chạy tuần tự (thế giới là trò chơi của tôi cập nhật thread):

Xem url như tôi không có đặc quyền hình ảnh: http://img849.imageshack.us/img849/9688/capturegff.png

Chủ đề dường như không thực thi mã cùng một lúc. Tôi khởi tạo chủ đề thế giới như sau:

public class World implements Runnable { 

    Thread thread; 

    public World(...) { 
    ... 
     // Initialise the player/ball objects 
     initialiseObjects(); 

     thread = new Thread(this, "World"); 
     thread.start(); 
} 
} 

Tôi đã thực hiện đồng bộ hóa riêng giữa hai chủ đề. Sử dụng một cách tiếp cận tương tự như trong Replica Island, tôi có hai bộ đệm render: thread cập nhật (nên lý tưởng) ghi vào một trong các bộ đệm trong khi thread render đang đọc bộ đệm khác. Bộ đệm chứa thông tin cần thiết cho trình kết xuất để vẽ từng ảnh. Một khi các chủ đề cập nhật đã hoàn thành cập nhật bộ đệm của nó và renderer đã hoàn thành bản vẽ, họ trao đổi bộ đệm và quá trình lặp đi lặp lại.

Trong mã từ các chủ đề trò chơi cập nhật (mã tương tự như trong render thread):

currBuffer.write(); 
    player.draw(currBuffer.getNext()); 

    ball.draw(currBuffer.getNext()); 

    if (particleEffect != null) { 
     particleEffect.draw(currBuffer); 
    } 

    currBuffer.finished(); 

    while(otherBuffer.isFinished() == false) { 
     //otherBuffer is finished once the render thread has finished drawing 
    } 

    DrawBuffer tempBuffer = currBuffer; 
    currBuffer = otherBuffer; 
    otherBuffer = tempBuffer; 

    currBuffer.changed(); 
    while(otherBuffer.isChanged() == false) { 
     //otherBuffer is changed once the render thread has also swapped buffered 
    } 

Tôi không thể nhìn thấy cách mã trên có thể dẫn đến việc thực hiện tuần tự các chủ đề, mặc dù tôi chưa bao giờ cố gắng đa luồng trước khi có thể tôi đang làm một cái gì đó về cơ bản sai. Nỗ lực của tôi để tăng tốc độ trò chơi đã làm cho nó đáng chú ý chậm hơn và kém trơn tru hơn nhiều. Bất kỳ ý tưởng tại sao các chủ đề không chạy song song?

CẬP NHẬT: Vấn đề là bộ xử lý của điện thoại của tôi chỉ là lõi đơn. Tôi chắc chắn rằng Incredible S là lõi kép nhưng than ôi nó chỉ là duy nhất. Tôi đã thử nó trên S2 và nó thực sự chạy các chủ đề song song.

Tuy nhiên, điều gì sau đó là lợi thế của đa luồng nếu chỉ có các điện thoại mới hơn trên thị trường hỗ trợ nó? Tôi không hiểu sao Replica Island quản lý hiệu suất tốt hơn trên các điện thoại lõi đơn cũ hơn bằng cách triển khai đa luồng. Chắc chắn các chi phí bổ sung trong đồng bộ hóa giữa các chủ đề sẽ dẫn đến hiệu suất chậm hơn nếu không có một lõi thứ hai để tận dụng lợi thế của?

Đa luồng dẫn đến hiệu suất chậm hơn trên lõi đơn do phải tạo bộ đệm sau đó được chuyển đến chuỗi vẽ. Trên lõi kép, nó đã được 5-10% nhanh hơn, mặc dù ở khoảng 500 sprites chu kỳ cập nhật mất nhiều thời gian hơn so với chu kỳ vẽ một lần nữa do bộ đệm, do đó hạn chế tốc độ tăng. Rõ ràng với tối ưu hóa, tôi có thể cải thiện điều đó nhưng câu hỏi trở thành liệu nó có đáng để hỗ trợ đa luồng với chi phí của các bộ vi xử lý lõi đơn hay không. Có thể xác định bộ xử lý của điện thoại để xác định xem có nên sử dụng đa luồng hay không khi chạy?

+0

Nếu bạn chỉ có một lõi đơn và cả hai tác vụ đều bị giới hạn CPU, thì chúng thực sự không thể chạy song song. Ngoài ra, những gì bên trong các vòng lặp 'while' này? Chúng thực sự là các vòng rỗng? –

+0

Cảm ơn @ David Schwartz - đó thực sự là vấn đề. Tôi chắc chắn rằng Incredible S là lõi kép nhưng than ôi nó chỉ là duy nhất. Tôi đã thử nó trên S2 và nó thực sự chạy các chủ đề song song. Tuy nhiên, những gì sau đó là lợi thế của đa luồng nếu chỉ có các điện thoại mới hơn trên thị trường hỗ trợ nó? Tôi không hiểu sao Replica Island quản lý hiệu suất tốt hơn trên các điện thoại lõi đơn cũ hơn bằng cách triển khai đa luồng. Chắc chắn các chi phí bổ sung trong đồng bộ hóa giữa các chủ đề sẽ dẫn đến hiệu suất chậm hơn nếu không có một lõi thứ hai để tận dụng lợi thế của? – awr

+0

Nếu các tác vụ không bị giới hạn CPU, có thể có những lợi ích to lớn cho việc đa luồng. Nếu một nhiệm vụ không thể thực hiện tiến trình chuyển tiếp (nói vì nó đang chờ I/O), một tác vụ khác có thể. Tuy nhiên, nếu chỉ có một lõi, và nhiệm vụ của bạn là CPU giới hạn, đa luồng sẽ không giúp đỡ. –

Trả lời

3

Vâng, về mặt kỹ thuật, 1 CPU chỉ chạy một đoạn mã tại một thời điểm. OS scheduler thay đổi các quy trình/chủ đề của bạn trong một phần nhỏ của mili giây cung cấp cho bạn ảo ảnh về việc chạy nhiều quy trình cùng một lúc.

Cách để thông báo thời gian chạy mà chuỗi của bạn được thực hiện ngay bây giờ là gọi Thread.yield. Có một vòng lặp bận rộn trong mã của bạn mà không giúp tình hình của bạn. Nó giữ cho CPU bận rộn w/o làm bất cứ điều gì.

while(otherBuffer.isFinished() == false) 

bạn nên sử dụng Loks thay vì vòng lặp bận rộn hoặc bạn có thể thử gọi Thread.yield bên trong vòng lặp while cho một tăng hiệu suất ban đầu. Btw, cũng hãy xem semaphore là giải pháp đơn giản nhất cho các vấn đề của người tiêu dùng sản xuất đó. Nếu bạn muốn giữ codebase hiện tại của mình, bạn có thể sử dụng khóa cho mỗi bộ đệm.

0

Tạo chủ đề như các lớp học như dưới đây

class Threadcalling implements Runnable 
    { 

     @Override 
     public void run() { 
} 
} 

nên gọi nó là sử dụng như dưới đây

Thread t=new Thread(new Threadcalling()); 
        t.start(); 

Bạn có thể tạo nhiều lớp chủ đề như thế này và gọi nó như song song. nó sẽ không tạo ra bất kỳ probs nào. làm việc tốt.