2009-11-21 36 views
7

Điển hình strlen() di chuyển ngang từ ký tự đầu tiên cho đến khi tìm thấy \0. Điều này yêu cầu bạn phải duyệt qua từng ký tự. Trong ý nghĩa thuật toán, O (N) của nó.strlen nhanh hơn?

Có cách nào nhanh hơn để thực hiện việc này khi đầu vào được xác định mơ hồ không. Giống như: độ dài sẽ nhỏ hơn 50 hoặc độ dài khoảng 200 ký tự.

Tôi đã nghĩ về các khối tra cứu và tất cả nhưng không nhận được bất kỳ tối ưu hóa nào.

+8

chắc. 'trả về 4;'. Đảm bảo được sét nhanh chóng! Con số được chọn bởi cuộn xúc xắc công bằng. – Geo

+1

@Geo [Cute] (https://xkcd.com/221/), nhưng điều đó không thực hiện 'strlen' cho phần lớn các yếu tố đầu vào. – imallett

Trả lời

17

Thực ra, glibc's implementation trong số strlen là một ví dụ thú vị về cách tiếp cận vector hóa.Đó là đặc biệt ở chỗ nó không sử dụng hướng dẫn vector, nhưng tìm thấy một cách để chỉ sử dụng hướng dẫn thông thường trên 32 hoặc 64 bit từ từ bộ đệm.

+0

thực sự rất thông minh! –

+0

Mặt khác, ít nhất là trên x86/x86_64 và gcc, bạn sẽ chỉ nhận được nội dung dựng sẵn của trình biên dịch. – LnxPrgr3

+0

Có, bạn phải cung cấp cho nó một tên khác nếu bạn muốn chắc chắn rằng phiên bản được sử dụng là của bạn. Nếu bạn định làm điều này, bạn cũng có thể đảm bảo rằng tất cả các chuỗi phiên bản của bạn sẽ được truyền đi là từ liên kết (nếu có thể) và loại bỏ hoàn toàn vòng lặp char-by-char hoàn toàn. –

22

Chắc chắn. Theo dõi độ dài trong khi bạn đang viết vào chuỗi.

+9

+1: Hooray pascal! –

+1

+1: Hoan hô Fortran (và không cho phép thay đổi nó theo bất kỳ cách nào sau khi khai báo) –

+0

tôi đã cải tiến lớn trên strcat sử dụng kỹ thuật này – Mandrake

6

Câu trả lời ngắn gọn: không.

Câu trả lời dài hơn: bạn có thực sự nghĩ rằng nếu có một cách nhanh hơn để kiểm tra độ dài chuỗi cho các chuỗi C của barebones, một cái gì đó thường được sử dụng như thư viện chuỗi C sẽ không kết hợp nó?

Nếu không có một số kiến ​​thức bổ sung về chuỗi, bạn phải kiểm tra từng ký tự. Nếu bạn sẵn sàng duy trì thông tin bổ sung đó, bạn có thể tạo struct lưu trữ độ dài dưới dạng trường trong cấu trúc (ngoài mảng ký tự/con trỏ thực tế cho chuỗi), trong trường hợp đó bạn có thể tạo độ dài tra cứu hằng số thời gian, nhưng sẽ phải cập nhật trường đó mỗi khi bạn sửa đổi chuỗi.

+0

Sau đó, chúng tôi lại có các chuỗi Pascal nữa. :) – wadesworld

+1

Nhưng chúng tôi có thể có ít bộ đệm hơn (nếu chúng được tích hợp sẵn trong ngôn ngữ hoặc được sử dụng nhất quán) - đó sẽ là một điều tốt! –

9

Rõ ràng, nếu chuỗi của bạn có độ dài tối thiểu đã biết, bạn có thể bắt đầu tìm kiếm tại vị trí đó.

Ngoài ra, bạn không thể thực hiện bất kỳ điều gì; nếu bạn cố gắng làm một cái gì đó thông minh và tìm thấy một byte \0, bạn vẫn cần kiểm tra từng byte giữa bắt đầu của chuỗi và điểm đó để đảm bảo rằng không có trước đó \0.

Điều đó không có nghĩa là không thể tối ưu hóa strlen. Nó có thể được pipelined, và nó có thể được thực hiện để xử lý kích thước từ hoặc khối vector với mỗi so sánh. Trên hầu hết các kiến ​​trúc, một số kết hợp của các phương pháp này và các phương pháp tiếp cận khác sẽ mang lại một sự tăng tốc liên tục đáng kể trên một vòng lặp so sánh byte ngây thơ. Tất nhiên, trên hầu hết các nền tảng trưởng thành, hệ thống strlen đã được triển khai bằng các kỹ thuật này.

3

Bạn có thể thử sử dụng vectơ. Không chắc chắn nếu trình biên dịch sẽ có thể thực hiện nó, nhưng tôi đã làm nó bằng tay (sử dụng nội tại). Nhưng nó có thể giúp bạn chỉ cho các chuỗi dài.

Sử dụng chuỗi stl, an toàn hơn và std :: lớp chuỗi chứa độ dài của nó.

+0

Làm thế nào vectorization có thể trợ giúp? Ngay cả khi bộ đệm được, nói rằng, 4 KB, không có đảm bảo về nội dung của chuỗi sau khi null đầu tiên, vì vậy nếu vectorization bắt đầu 4 hoạt động (chủ đề?) Trên ranh giới 1 KB, không có nói những gì ba bắt đầu từ một khoản chênh lệch khác 0 sẽ thấy. Tôi cho rằng kết quả sẽ phải là giá trị tối thiểu của 4 giá trị trả về - trong đó các chuỗi offset khác 0 sẽ phải thêm vị trí bắt đầu của chúng vào chiều dài trả về. –

+0

Tôi nghĩ rằng Elalfer đang đề xuất gán từng byte liên tiếp cho một vectơ để được kiểm tra tổng thể và sau đó cuộn quét chuỗi chiều dài của vectơ. Điều đó chắc chắn sẽ hoạt động, giả sử bạn có một kiến ​​trúc dựa trên vector. –

+2

@Jonathan Vectorization không sử dụng chủ đề! Vectorization có nghĩa là sử dụng mô hình lập trình SIMD để kiểm tra các byte liên tiếp cho số không đồng thời. http://en.wikipedia.org/wiki/SIMD Nó giúp liên kết vectơ luôn làm cho chúng phù hợp trong một trang duy nhất. Việc triển khai này thường tràn bộ đệm nhưng không bị MMU bắt giữ. Chúng tôi tìm thấy những tràn bộ đệm lành tính trong phân tích tôi làm việc trên. Xem thêm http://tsunanet.net/~tsuna/strlen.c.html để triển khai C ấn tượng mà không cần hướng dẫn vector đặc biệt. –

4

Jack,

strlen tác phẩm bằng cách tìm kiếm kết thúc '\ 0', đây là một thực hiện lấy từ OpenBSD:

size_t 
strlen(const char *str) 
{ 
     const char *s; 

     for (s = str; *s; ++s) 
       ; 
     return (s - str); 
} 

Bây giờ, hãy xem xét mà bạn biết chiều dài là khoảng 200 ký tự, như bạn đã nói. Giả sử bạn bắt đầu từ 200 và lặp lên và xuống cho '\ 0'. Bạn đã tìm thấy một ở 204, có nghĩa là gì? Đó là chuỗi dài 204 ký tự? KHÔNG! Nó có thể kết thúc trước đó với một '\ 0' và tất cả những gì bạn đã làm là nhìn ra ngoài giới hạn.

+0

Cảm ơn câu trả lời. Như tôi đã nói, chiều dài được dự đoán mơ hồ và có thể không kết thúc sau ký tự 200. Ngoài ra, nếu chúng ta bắt đầu đọc sau ký tự thứ 200, chúng ta có thể đọc chuỗi không hợp lệ (nếu chuỗi kết thúc khoảng 100 ký tự ...) – Jack

+0

Liên kết cũng nói giống nhau: http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/strlen.c?annotate=1.7 – Jack

3

Nhận bộ xử lý Core i7.

Core i7 đi kèm với bộ chỉ lệnh SSE 4.2. Intel đã thêm bốn hướng dẫn vector bổ sung để tăng tốc các tác vụ tìm kiếm liên quan và strlen.

Dưới đây là một vài suy nghĩ thú vị về các hướng dẫn mới:

http://smallcode.weblogs.us/oldblog/2007/11/

+0

Cảm ơn bạn đã trả lời. Như George Verghese nói, tăng cường phần cứng luôn giúp :) – Jack