Hỏi về 1 vài khái niệm trong C

Ngày trước đi học em có được nghe thấy 1 vài thứ thấy hay hay. Giờ nhớ là vậy nhưng không biết giải thích lại như thế nào. Có ai giúp em với ạ

  1. Là liên quan đến giá trị trả về của 1 hàm. Ví dụ: Mình viết 1 hàm tìm số chẵn. Nếu tìm thấy số chẵn thì return 0, nếu ko thấy sẽ return 1, còn lỗi kiểu như người dùng ko nhập vào số thì return -1
    Thì em nhớ nhớ là return 0 trong cái trường hợp mình tìm được số chẵn là bởi vì phép so sánh if(var == 0) nó nhanh hơn if(var == 1) hay sao ấy. Còn vì sao nhanh hơn thì e lại ko nhớ
  2. E có nghe thấy là khi compiler nó tối ưu code nó sẽ có tùy chọn giữa tối ưu về tốc độ hoặc về kích thước chương trình. Nhưng nếu mình chọn tối ưu cho size, mà khi size nó giảm nhiều thì tốc độ lại giảm. Nghe nó cứ hơi ngược, bởi e nghĩ size giảm thì tốc độ phải tăng chứ ạ
  1. Return cái gì tuỳ cách tư duy và thiết kế, quy ước của người thực hiện hoặc nhóm thực hiện. Thường người ta sẽ return 1 khi hợp lệ vì 1 tương đương true. Nên khi viết thế này nó sẽ xuôi:
if(isEvenNumber(input)){}

Tốc độ so sánh thì tuỳ loại chip nhưng thường là ngang nhau. Nguyên nhân do chip có hỗ trợ lệnh nhảy khi so sánh 0 và so sánh khác không hay không. Nhưng nó chỉ lệnh nhau 1-2 lệnh nên trên tổng thể coi như là bằng nhau.

  1. Nhà bạn giàu, xây to có 4 cái nhà vệ sinh (size) thì bạn giải quyết cũng nhanh (speed) và thoải mái hơn trong cái trường hợp ít tiền và nhỏ xíu đi vệ sinh cũng phải chờ nhau vì có mỗi cái nhà vệ sinh.
10 Likes
  1. CPU đều có 1 thanh ghi gọi là thanh ghi zero. Nên khi so sánh với 0 thì chỉ cần mang thanh ghi chứa số cần so sánh compare được luôn. So sánh với hằng số khác thì cần load hằng số đó lên một thanh ghi khác rồi thực hiện so sánh, chậm hơn 1-2 chu kì lệnh gì đó. Nói chung là không đáng kể. Không cần quan tâm lắm.
  2. Khi thực hiện cùng một công việc, bạn càng được chỉ dẫn chi tiết (chương trình nhiều hơn) thì bạn làm càng nhanh và ngược lại.
    Có một cách để bạn thấy được vấn đề này là bạn compiler ra asembly rồi sau đó đọc mã asm đó là sẽ hiểu.
    Tôi có 1 ví dụ đơn giản dạng mã giả asm như thế này:
    ① Tối ưu size:
Start
load RegB 250
compare RegA RegB
jpm End
#copy 4 bytes src to dst
add RegA 4
jmp Start
End

② Tối ưu tốc độ:

Start
load RegB 31
compare RegA RegB
jpm End1
#copy 4 bytes src to dst
#copy 4 bytes src to dst
#copy 4 bytes src to dst
#copy 4 bytes src to dst
#copy 4 bytes src to dst
#copy 4 bytes src to dst
#copy 4 bytes src to dst
#copy 4 bytes src to dst
add RegA 32
jmp Start
End1
#copy 4 bytes src to dst
#copy 4 bytes src to dst
End
5 Likes

Em cảm ơn anh nhiều nhé.

Em cảm ơn anh nhiều nhé

Có những thứ nghe có vẻ hay đó bạn, nhưng hoặc là do bản thân chưa đủ kiến thức để hiểu hết, hoặc do người nói cũng chưa hiểu hết mà phát biểu nên luôn cần phải tự mình kiểm chứng mới có khả năng đáng tin nha bạn.

Về topic như này thì không thể nào bỏ qua phần đọc mã asm cả (và nó sẽ phụ thuộc vào từng platform/compiler)

Về điều thứ nhất, return 0 hay return 1 tốt hơn? Thì câu trả lời sẽ là return cái nào hợp lý. Đây là code mẫu: https://godbolt.org/z/sfhxqP. Mặc dù is_even0is_even khi biên dịch sẽ ra mã asm khác nhau, is_even0 lại giống is_odd, nhưng khi dùng thì cả 3 đều cho cùng mã asm. Nên vấn đề bây giờ chỉ là nhìn code C++ thì bạn thấy cái nào hợp lý hơn? Dĩ nhiên là code is_odd hoặc code is_even rồi

Về điều thứ hai, ở đây có vẻ bạn hiểu nhầm, khi optimize theo size, thì compiler sẽ chọn những cái optimize nào mà không làm tăng kích thước file binary, chứ không phải là sẽ không optimize, nên “về lý thuyết” thì optimize theo size sẽ chậm hơn optimize theo speed, chứ không phải là chậm hơn cả khi không optimize. Và không phải cứ phải chương trình to/chỉ dẫn cụ thể là sẽ chạy nhanh đâu, chỉ có 1 vài trường hợp optimize sẽ làm tăng kích thước như: loop unroll, inline, … (điểm chung thường là tránh branching/jmp nhiều mà thôi)

6 Likes

Mình chọn biên dịch cho 1 con vi điều khiển hay được sử dụng là AVR. So sánh với 0 vẫn được tối ưu asm hơn. Có thể không nhiều. Nhưng như chủ thread nói, hơn thì vẫn là hơn

6 Likes

Đúng là nó sẽ còn phụ thuộc platform. Nhưng mà is_evenreturn 0 khi true thì đúng ra nên đặt tên nó là is_odd. Rõ ràng là code dùng is_oddis_even0 trong hình là y như nhau => đừng bao giờ viết is_even0 làm gì cả.

Code mới optimize cho avr: https://godbolt.org/z/57fboE

5 Likes

Nó phụ thuộc loại CPU. Compiler.
Không phải chỗ nào so sánh 0 cũng đều nhanh hơn.

4 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?