Announcement

Collapse
No announcement yet.

[Help] Tối ưu code C

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • [Ansi C] [Help] Tối ưu code C

    Đề bài là tìm số nguyên tố thứ n. n<10000, thời gian 1s.
    Input N
    Ouput M
    VD
    Input
    3
    Output
    5
    ---
    Em mới làm xong, không biết có cách nào tối ưu hơn được nữa không ạ?
    Code bên dưới với n<3600, t<1s, nhưng n>3600, t>1s
    Anh chị xem giùm, chỉ dẫn em với ạ.

    PHP Code:
    #include <stdio.h>
    #include <stdlib.h>

    charinputDirect"input.txt";
    charoutputDirect"output.txt";
    int numIn;
    int length;
    intnumArr;
    int IsPrime(int num);
    void ReadInput();
    void WriteOutput();
    int main()
    {
        
    ReadInput();
        
    lengthnumIn*numIn;
        
    numArr= (int*)calloc(length,sizeof(int));
        
    long int ij;
        for(
    i=0;i<length;i++)
        {
            
    numArr[i]= 1;
        }
        for(
    i=2;i*i<=length;i++)
        {
            if(
    numArr[i]==1)
            {
                for(
    j=i;i*j<=length;j++)
                {
                    
    numArr[i*j]=0;
                }
            }
        }
        
    WriteOutput();
        return 
    0;
    }
    void ReadInput()
    {
        
    FILEffopen(inputDirect,"r");
        if(
    f)
        {
            
    fscanf(f,"%d",&numIn);
            
    fclose(f);
        }
    }
    void WriteOutput()
    {
        
    int icount0;
        
    FILEffopen(outputDirect,"w");
        if(
    f)
        {
            for(
    i=2;i<length;i++)
            {
                if(
    numArr[i]==1)
                {
                    
    count++;
                }
                if(
    count==numIn)
                {
                    
    fprintf(f,"%d",i);
                    
    fclose(f);
                    return;
                }
            }
            
    fprintf(f,"-1");
            
    fclose(f);
        }
    }
    int IsPrime(int num)
    {
        if(
    num<2)
        {
            return 
    0;
        }
        if(
    num==2)
        {
            return 
    1;
        }
        if(
    num%2==0)
        {
            return 
    0;
        }
        
    int i;
        for(
    i=3;i*i<=num;i+=2)
        {
            if(
    num%i==0)
            {
                return 
    0;
            }
        }
        return 
    1;

    Last edited by Guest; 14-11-2011, 12:44.

  • #2
    Em chờ sau ngày 19/11 nha em... =))
    Khoảng cách giữa bạn và ước mơ của bạn là bao xa ?

    Comment


    • #3
      Giống cái đề thi lập trình do đoàn trường tổ chức quá bay =))

      Comment


      • #4
        Góp ý chút xíu cho bạn về hàm kiểm tra số nguyên tố của bạn viết hơi dài dòng và dư thừa.

        Comment


        • #5
          Originally posted by 07520004 View Post
          Giống cái đề thi lập trình do đoàn trường tổ chức quá bay =))
          chính là nó đấy
          Hãy là chính mình!

          Comment


          • #6
            Originally posted by 08520348 View Post
            Góp ý chút xíu cho bạn về hàm kiểm tra số nguyên tố của bạn viết hơi dài dòng và dư thừa.
            Hàm kiểm tra số nguyên tố chỉ phải chạy từ 3 đến sqrt(n), mỗi lần tăng là 2, nên nó chỉ lặp có sqrt(n)/2 lần.
            Nhanh gấp đôi so với cái từ 2 đến sqrt(n), mỗi lần tăng 1, là lặp sqrt(n) lần mà.
            Khúc đầu thì hơi rườm rà, không biết tối ưu thêm.

            Mà chương trình này đâu có cần dùng hàm đó đâu. Code chơi thôi. Chương trình sử dụng thuật toán sàng nguyên tố mà.

            Comment


            • #7
              muốn nhanh thì code bằng Verilog, nhanh nhất luôn :-p. Còn tối ưu mã C, thì theo kinh nghiệm lập trình nhúng của tui ( ý kiến chủ quan ). Vòng while sẽ nhanh hơn for, i-- sẽ nhanh hơn i++, và phép dịch bit nhanh hơn nhân/chia. Kiểu dữ liệu càng ngắn(tính theo byte nha) thì tốc độ truy xuất càng nhanh ==> giảm thời gian trễ. Còn tối ưu về khía cạnh thuật toán thì, không dám múa rìu qua mắt thợ
              Một khẩu súng giữ hai trời Nam Bắc,
              Một dấu chân in màu đất hai miền.

              ------------------------------------------------------

              Comment


              • #8
                Originally posted by 08520229 View Post
                muốn nhanh thì code bằng Verilog, nhanh nhất luôn :-p. Còn tối ưu mã C, thì theo kinh nghiệm lập trình nhúng của tui ( ý kiến chủ quan ). Vòng while sẽ nhanh hơn for, i-- sẽ nhanh hơn i++, và phép dịch bit nhanh hơn nhân/chia. Kiểu dữ liệu càng ngắn(tính theo byte nha) thì tốc độ truy xuất càng nhanh ==> giảm thời gian trễ. Còn tối ưu về khía cạnh thuật toán thì, không dám múa rìu qua mắt thợ
                giảm vậy được bao nhiêu mili giây ?

                đối với các dòng CPU máy vi tính thì mỗi instruction chạy gần như như nhau rồi Nhân chia 2 số nguyên = phép dịch bit. Nhân chia 2 số thực = mã hợp ngữ sin / cos / pow. Tại sao phải tội vạ gì đi tối ưu những thứ ko cần thiết ?
                Khoảng cách giữa bạn và ước mơ của bạn là bao xa ?

                Comment


                • #9
                  Originally posted by 09520019 View Post
                  giảm vậy được bao nhiêu mili giây ?

                  đối với các dòng CPU máy vi tính thì mỗi instruction chạy gần như như nhau rồi Nhân chia 2 số nguyên = phép dịch bit. Nhân chia 2 số thực = mã hợp ngữ sin / cos / pow. Tại sao phải tội vạ gì đi tối ưu những thứ ko cần thiết ?
                  Ý kiến cá nhân của người ta thôi. Trên các CPU đời cũ tập lệnh hạn chế thì những điều đó đều nghiệm đúng cả mà, bắt bẻ chi nặng lời vậy.

                  Comment


                  • #10
                    Originally posted by 09520019 View Post
                    giảm vậy được bao nhiêu mili giây ?

                    đối với các dòng CPU máy vi tính thì mỗi instruction chạy gần như như nhau rồi Nhân chia 2 số nguyên = phép dịch bit. Nhân chia 2 số thực = mã hợp ngữ sin / cos / pow. Tại sao phải tội vạ gì đi tối ưu những thứ ko cần thiết ?
                    làm trên vi điều khiển thì giảm được kha khá đấy... Trong máy tính (cụ thể là CPU)để thực hiện phép nhân thì nó phải thực hiện nhiều lần phép cộng. ví dụ 3 * a thì nó sẽ làm a+a+a, giả sử 1 lệnh cần 5 chu kì xung clock (tạm gọi là thế) thì 3 cái lệnh cộng đó sẽ ngốn 15 chu kì (dĩ nhiên là CPU đời mới nó có cái vụ pipeline để tăng tốc nhưng mà cái này nó cần kết quả của phép tính trước nên kiểu gì cũng phải đợi, dĩ nhiên Pipeline trong CPU hiện đại giờ ko cần tốn 15 chu kì để làm cái vụ này nhưng tạm thời thế đi), để thực hiện phép dịch a<<1+1 (<==> a*2 + 1) thì nó chỉ cần dùng thanh ghi dịch và 1 phép cộng --> tốn 6 chu kì ==> bằng 1/2 cách kia.... cũng đáng kể đấy chứ nhỉ ... Nhưng mà nói đi thì phải nói lại, tốc độ xử lý Chip CPU nó lên tới hàng GHz nên kể ra thì người xài PC, cũng chả ai rỗi hơi đi để ý để thấy sự khác biệt của 2 cách này, nhưng mà tại mình làm trên mấy dòng "con nhà nghèo" như 8051, PIC, ARM tốc độ xử lý vài chục MHz, ram cũng chỉ cỡ vài KB à nên phải tiết kiệm :-p.

                    Dĩ nhiên đây là tối ưu bằng Kĩ thuât, tối ưu bằng thuật toán là tốt nhất... nhưng có những thuật toán không thẻ nào tối ưu hơn đc nữa thì xài cái này cũng nhanh được tí chút
                    Last edited by 08520229; 14-11-2011, 21:53.
                    Một khẩu súng giữ hai trời Nam Bắc,
                    Một dấu chân in màu đất hai miền.

                    ------------------------------------------------------

                    Comment


                    • #11
                      Anh nói đúng. Nếu xét xuống từng xung nhịp CPU thì rõ ràng là phép dịch bit < cộng trừ < nhân < chia nhưng mà bài này là làm trên máy chạy Core Duo trở lên chứ ko phải chạy trên mấy máy 8086 nên không cần phải tối ưu như thế. Chưa kể một vài bài em làm 1 soft nhỏ thì thời gian chạy của việc dùng if (a % 2 == 1) so với if (a >> 1) không khác nhau là bao về thời gian chạy, mặc dù đoạn lệnh thứ nhất sử dụng 1 phép chia, 1 phép trừ so với đoạn thứ 2 dùng 1 phép dịch bit.
                      Chưa kể là rõ ràng CPU đời mới chậm không phải do xung nhịp CPU mà là do thời gian nạp dữ liệu từ RAM/Cache vào thanh ghi. Mỗi lần CPU xử lý 1 lệnh có tốc độ gấp 1000 lần so với việc nạp 1 dữ liệu từ RAM lên CPU nên tối ưu vậy không cần thiết đâu anh. Bài bạn kia làm là do đọc không kỹ đề đó.Với lại em không có ý nặng gì đâu chỉ là thấy thiên hạ hè nhau tối ưu hết cỡ mà code sau đó thì rất khó hiểu nên em bắt bẻ vậy thôi. Post trước với post này có gì nặng lời thì bỏ qua há tại vì em ko có nặng lời.

                      @Anh An: Em có nói nặng huh :-? Anh có nước xả làm mềm không
                      Last edited by 09520019; 14-11-2011, 22:35.
                      Khoảng cách giữa bạn và ước mơ của bạn là bao xa ?

                      Comment


                      • #12
                        có gì đâu mà nặng lời... cái này là do mình học KTMT, làm việc với vi điều khiển quen rồi, mà chủ yếu là viết dạng firmware nên gợi ý như thế. Trên vi điều khiển thì không có sung sướng như trên PC nên mình chỉ đưa ra một số ý kiến thế thôi. Còn vấn đề bạn nói, ừ đúng nhưng nó không liên quan gì đến chuyện mình đề cập. Cái mình nói là cách thức làm việc của CPU khi gặp lệnh + và <<, còn cache với bus lại là chuyện khác, đó chỉ là 1 trong hàng tá cái người ta tích hợp vào CPU để tăng tốc xử lý, như bộ tiên đoán lệnh, CacheL1,L2,L3, MMU... thậm chí ngay cả ALU cũng đc thêm vào hàng tá thứ chứ không chỉ có mạch cộng/trừ như 8086(bộ xử lý dấu chấm động...) nhưng có thêm thế nào thì CPU vẫn là CPU và cơ chế hoạt động của nó đến bây giờ vẫn vậy -- tuy nhiện vụ này phải đi tranh luận chỗ khác (ở đây chẳng hạn http://www.uit.edu.vn/forum/index.php?showforum=267) chứ không mod xử đẹp .

                        Nếu như bạn có dịp làm việc với 8051 thì bạn sẽ thấy đc vấn đề. Dĩ nhiên là 2 cái chĩ chậm hơn vài ms, nhưng mà nếu cộng dồn lại thì lại là chuyện khác. Nhưng đúng thật là nếu code bằng C# hay C++ thì chả hơn đc bao nhiêu, vì trình biên dịch của 2 cái này không đặt nặng lắm vấn đề tối ưu mã ASM... Nếu code C hoặc thấp hơn là ASM thì sẽ đụng những vấn đề này

                        Thân

                        PS: một lần cãi nhau thế này là một lần mình hệ thống lại kiến thức + lục lọi lại tài liệu nên khuyến khích tranh luận. Hì hì
                        Last edited by 08520229; 14-11-2011, 22:48.
                        Một khẩu súng giữ hai trời Nam Bắc,
                        Một dấu chân in màu đất hai miền.

                        ------------------------------------------------------

                        Comment


                        • #13
                          Về hàm IsPrime các anh nói đều hay đều đúng và em cũng không có gì để nói tiếp.
                          Em có ghi ở post #6 mà, các đó là code chơi thôi, chương trình hoàn toàn không sử dụng đến hàm đó, tại để đó mà không xóa thôi. làm biếng.

                          Comment


                          • #14
                            Originally posted by Mới học C View Post
                            Về hàm IsPrime các anh nói đều hay đều đúng và em cũng không có gì để nói tiếp.
                            Em có ghi ở post #6 mà, các đó là code chơi thôi, chương trình hoàn toàn không sử dụng đến hàm đó, tại để đó mà không xóa thôi. làm biếng.
                            Chờ đợi đi bạn, 19/11 mình bảo đảm sẽ có code tối ưu hơn rất nhiều(chạy được 50000 trong 1s là rất bình thường), tại trường mình đang tổ chức thi có câu giống y câu này nên các Uiter không share cho bạn được
                            Last edited by 09520668; 15-11-2011, 12:49.

                            Comment


                            • #15
                              Originally posted by Mới học C View Post
                              Hàm kiểm tra số nguyên tố chỉ phải chạy từ 3 đến sqrt(n), mỗi lần tăng là 2, nên nó chỉ lặp có sqrt(n)/2 lần.
                              Nhanh gấp đôi so với cái từ 2 đến sqrt(n), mỗi lần tăng 1, là lặp sqrt(n) lần mà.
                              Khúc đầu thì hơi rườm rà, không biết tối ưu thêm.
                              Hàm KT số Nguyên tố thực ra đâu cần chạy từ 3, mỗi lần tăng 2. Có một cách khá tối tưu trong việc kiểm tra số nguyên tố:
                              PHP Code:
                              bool isPrime(int n)
                              {
                               if(
                              == || == 3)
                                return 
                              true;
                               if (
                              n<2||== 0||== 0)
                                return 
                              false;
                               
                              int m = (int)sqrt(n); //dat gia tri sqrt(n) ra de moi lan lap khong can tinh' lai
                               
                              for(int i=5;i<=m;i=i+6)
                                if(
                              == || % (i+2) == 0) return false;
                               return 
                              true;

                              Anh em tự nghiên cứu nha.
                              https://fbcdn-photos-a.akamaihd.net/...08264688_a.jpg

                              Comment

                              LHQC

                              Collapse
                              Working...
                              X