рдпрд╣ рд╕реБрдиреНрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓реЗрдЦ рдХрд╛ рджреВрд╕рд░рд╛ рднрд╛рдЧ рд╣реИред рдкрд╣рд▓рд╛ рдРрддрд┐рд╣рд╛рд╕рд┐рдХ рдкрд░рд┐рдЪрдп рдФрд░ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╕реБрдЪрдирд╛ рдирд┐рд░реНрджреЗрд╢ рдкреБрд╕реНрддрд┐рдХрд╛ рдереАред рдпрд╣рд╛рдБ рдореИрдВ рд╣рд╛рд╕реНрдХреЗрд▓ рд▓реЗрдЦ " рд╕реА + + рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рддреЗрдЬрд╝ " рд╕реЗ рдереЛрдбрд╝рд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд╛рд░реНрдп рдХреЛрдб рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реВрдВ ; PHP рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдзреАрдореА "(рдпрд╣ рд╡рд┐рднрд┐рдиреНрди рднрд╛рд╖рд╛рдУрдВ / рд╕рдВрдХрд▓рдХ рдореЗрдВ рдПрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреА рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИ) рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рдмреЗрдВрдЪрдорд╛рд░реНрдХ, рдЧреНрд░рд╛рдлрд╝ рдФрд░ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреЗ рд╕рд╛рдеред рдореИрдВ рдЕрднреА рдпрд╣ рдХрд╣рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ рдореИрдВрдиреЗ рд▓реЗрдЦ рдУрд╣ рджреЗрдЦрд╛ , рдпрд╣ рдзреАрдорд╛ C / C ++ рдФрд░, рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ, рдпрджрд┐ рдЖрдк C рдХреЛрдб рдореЗрдВ рдпреЗ рдмрджрд▓рд╛рд╡ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рддрд╕реНрд╡реАрд░ рдереЛрдбрд╝реА рдмрджрд▓ рдЬрд╛рдПрдЧреА, рд▓реЗрдХрд┐рди рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рднреА, рдЕрдЬрдЧрд░ рдЗрд╕ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рднреА C рдХреА рдЧрддрд┐ рдХреЛ рдкрд╛рд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рд╣реИред

рдЕрдЬрдЧрд░ рдХреА рд╕реВрдЪреА рдХреЛ рдПрдХ рд╕реБрд╕реНрдкрд╖реНрдЯ рд╕рд░рдгреА рдХреЗ рд╕рд╛рде рдмрджрд▓рд╛ рдЧрдпрд╛ (рдФрд░, рддрджрдиреБрд╕рд╛рд░, v0[:]
v0.copy()
, рдХреНрдпреЛрдВрдХрд┐ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рд░реВрдк рд╕реЗ a[:]
рдирдХрд▓ рдХреЗ рдмрдЬрд╛рдп view
рд▓реМрдЯрд╛рддрд╛ рд╣реИ)ред
рдкреНрд░рджрд░реНрд╢рди рд╡реНрдпрд╡рд╣рд╛рд░ рдХреА рдкреНрд░рдХреГрддрд┐ рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕рд░рдгреА рдореЗрдВ рддрддреНрд╡реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рдПрдХ "рд╕реНрдХреИрди" рдХрд┐рдпрд╛ред
рдкрд╛рдпрдерди рдХреЛрдб рдореЗрдВ, рдореИрдВрдиреЗ time.monotonic
рдХреЛ time.monotonic
рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд╣реИ (рдореЛрдиреЛрдЯреЛрдирд┐рдХ рдХреЗ рд▓рд┐рдП 1us рдмрдирд╛рдо 1ms)ред
рдЪреВрдВрдХрд┐ рд╕реБрдВрдмрд╛ рдЬреАрдЯ рд╕рдВрдХрд▓рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХрд┐рд╕реА рджрд┐рди рдпрд╣ рд╕рдВрдХрд▓рди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рдпрд╣ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд╣рд▓реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдорд╛рдирджрдВрдб рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрджрд┐ рдЖрдк рддреАрди рд▓реЙрдиреНрдЪ рд╕реЗ рд╕рдордп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕ рдкрд░ рдзреНрдпрд╛рди рдирд╣реАрдВ рджреЗ рд╕рдХрддреЗ рд╣реИрдВ), рдФрд░ рдпрд╣ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдЙрдкрдпреЛрдЧ рдореЗрдВ рднреА рдорд╣рд╕реВрд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рдШрдЯрдирд╛ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рдХрдИ рддрд░реАрдХреЗ рд╣реИрдВ:
1) рдХреИрд╢ рд╕рдВрдХрд▓рди рдбрд┐рд╕реНрдХ рдкрд░ рдкрд░рд┐рдгрд╛рдо:
@njit(cache=True) def lev_dist(s1: AnyStr, s2: AnyStr) -> int:
рддрдм рд╕рдВрдХрд▓рди рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдкрд╣рд▓реЗ рдХреЙрд▓ рдкрд░ рд╣реЛрдЧрд╛, рдФрд░ рдмрд╛рдж рдореЗрдВ рдХреЙрд▓ рдбрд┐рд╕реНрдХ рд╕реЗ рдЦреАрдВрдЪреА рдЬрд╛рдПрдЧреАред
2) рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВ
рд╕рдВрдХрд▓рди рдЙрд╕ рд╕рдордп рд╣реЛрдЧрд╛ рдЬрдм рдЕрдЬрдЧрд░ рдлрд╝рдВрдХреНрд╢рди рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдкрд╣рд▓реА рд╢реБрд░реБрдЖрдд рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рддреЗрдЬ рд╣реЛрдЧреАред
рдореВрд▓ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕рдВрдЪрд░рд┐рдд рд╣реЛрддреА рд╣реИ (рдЕрдзрд┐рдХ рд╕рдЯреАрдХ, рдмрд╛рдЗрдЯреНрд╕), рд▓реЗрдХрд┐рди рддрд╛рд░ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд╛рдлреА рд░рд╛рдХреНрд╖рд╕реА рд╣реИ (рдиреАрдЪреЗ рджреЗрдЦреЗрдВ)ред рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЖрдорддреМрд░ рдкрд░ рд╕рд░рд▓ рд▓рд┐рдЦреЗ рдЬрд╛рддреЗ рд╣реИрдВ:
@njit(nb.int64(nb.uint8[:], nb.uint8[:])) def lev_dist(s1, s2):
рд▓реЗрдХрд┐рди рдлрд┐рд░ рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рдмрд╛рдЗрдЯреНрд╕ рдХреЛ рдПрдХ рдЦрд╕реНрддрд╛ рд╕рд░рдгреА рдореЗрдВ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛:
s1_py = [int(x) for x in b"a" * 15000] s1 = np.array(s1_py, dtype=np.uint8)
рдпрд╛
s1 = np.full(15000, ord('a'), dtype=np.uint8)
рдФрд░ рдЖрдк рдмрд╛рдЗрдЯреНрд╕ рдХреЛ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕ рд░реВрдк рдореЗрдВ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
@njit(nb.int64(nb.bytes(nb.uint8, nb.1d, nb.C), nb.bytes(nb.uint8, nb.1d, nb.C))) def lev_dist(s1: AnyStr, s2: AnyStr) -> int:
рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдирд┐рд╖реНрдкрд╛рджрди рдХреА рдЧрддрд┐ рдФрд░ uint8 рд╕реЗ рд╕реБрдиреНрди рд╕рд░рдгреА (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ) рд╕рдорд╛рди рд╣реИред
3) рдХреИрд╢ рдХреЛ рдкреНрд░реАрд╣реАрдЯ рдХрд░реЗрдВ
s1 = b"a" * 15
рдлрд┐рд░ рд╕рдВрдХрд▓рди рдкрд╣рд▓реА рдХреЙрд▓ рдкрд░ рд╣реЛрдЧрд╛, рдФрд░ рджреВрд╕рд░рд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рддреЗрдЬ рд╣реЛрдЧрд╛ред
рдкрд╛рдпрдерди рдХреЛрдб C рдХреЛрдб (clang -O3 -march = рджреЗрд╢реА) #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> static long lev_dist (const char *s1, unsigned long m, const char *s2, unsigned long n) { // unsigned long m, n; unsigned long i, j; long *v0, *v1; long ret, *temp; /* Edge cases. */ if (m == 0) { return n; } else if (n == 0) { return m; } v0 = malloc (sizeof (long) * (n + 1)); v1 = malloc (sizeof (long) * (n + 1)); if (v0 == NULL || v1 == NULL) { fprintf (stderr, "failed to allocate memory\n"); exit (-1); } for (i = 0; i <= n; ++i) { v0[i] = i; } memcpy (v1, v0, sizeof(long) * (n + 1)); for (i = 0; i < m; ++i) { v1[0] = i + 1; for (j = 0; j < n; ++j) { const long subst_cost = (s1[i] == s2[j]) ? v0[j] : (v0[j] + 1); const long del_cost = v0[j + 1] + 1; const long ins_cost = v1[j] + 1; #if !defined(__GNUC__) || defined(__llvm__) if (subst_cost < del_cost) { v1[j + 1] = subst_cost; } else { v1[j + 1] = del_cost; } #else v1[j + 1] = (subst_cost < del_cost) ? subst_cost : del_cost; #endif if (ins_cost < v1[j + 1]) { v1[j + 1] = ins_cost; } } temp = v0; v0 = v1; v1 = temp; } ret = v0[n]; free (v0); free (v1); return ret; } int main () { char s1[25001], s2[25001], s3[25001]; int lengths[] = {1000, 2000, 5000, 10000, 15000, 20000, 25000}; FILE *fout; fopen_s(&fout, "c.txt", "w"); for(int j = 0; j < sizeof(lengths)/sizeof(lengths[0]); j++){ int len = lengths[j]; int i; clock_t start_time, exec_time; for (i = 0; i < len; ++i) { s1[i] = 'a'; s2[i] = 'a'; s3[i] = 'b'; } s1[len] = s2[len] = s3[len] = '\0'; start_time = clock (); printf ("%ld\n", lev_dist (s1, len, s2, len)); printf ("%ld\n", lev_dist (s1, len, s3, len)); exec_time = clock () - start_time; fprintf(fout, "%d %.6f\n", len, ((double) exec_time) / CLOCKS_PER_SEC); fprintf (stderr, "Finished in %.3fs\n", ((double) exec_time) / CLOCKS_PER_SEC); } return 0; }
рддреБрд▓рдирд╛ рд╡рд┐рдВрдбреЛрдЬрд╝ (рд╡рд┐рдВрдбреЛрдЬрд╝ 10 x64, рдкрд╛рдпрдерди 3.7.3, рд╕реБрдВрдмрд╛ 0.45.1, рдХреНрд▓реИрдЧ 9.0.0, рдЗрдВрдЯреЗрд▓ m5-6y54 рд╕реНрдХрд╛рдИрд▓реЗрдХ) рдХреЗ рддрд╣рдд рдХреА рдЧрдИ рдереА: рдФрд░ рд▓рд┐рдирдХреНрд╕ рдХреЗ рдиреАрдЪреЗ (рдбреЗрдмрд┐рдпрди 4.9.30, рдкрд╛рдпрдереЙрди 3.7.4, рд╕реБрдВрдмрд╛ 0.45.1)ред clang 9.0.0)ред
X рд╕рд░рдгреА рдХрд╛ рдЖрдХрд╛рд░ рд╣реИ, y рд╕реЗрдХрдВрдб рдореЗрдВ рд╕рдордп рд╣реИред
рд╡рд┐рдВрдбреЛрдЬ рд░реИрдЦрд┐рдХ рдкреИрдорд╛рдиреЗ:

рд╡рд┐рдВрдбреЛрдЬ рд▓реЙрдЧрд░рд┐рджрдорд┐рдХ рд╕реНрдХреЗрд▓:

рд▓рд┐рдирдХреНрд╕ рд░реИрдЦрд┐рдХ рд╕реНрдХреЗрд▓:

рд▓рд┐рдирдХреНрд╕ рд▓реЙрдЧрд░рд┐рджрдорд┐рдХ рд╕реНрдХреЗрд▓

рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдореЗрдВ, рдХрдИ рдкреНрд░рддрд┐рд╢рдд рдХреЗ рд╕реНрддрд░ рдкрд░ рдХреНрд▓реИрдВрдЧ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЧрддрд┐ рдореЗрдВ рд╡реГрджреНрдзрд┐ рдкреНрд░рд╛рдкреНрдд рдХреА рдЧрдИ рдереА, рдЬреЛ рдЖрдорддреМрд░ рдкрд░ рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рддреНрд░реБрдЯрд┐ рд╕реЗ рдЕрдзрд┐рдХ рд╣реИред
рдореИрдВрдиреЗ рдмрд╛рд░-рдмрд╛рд░ рд╡рд┐рднрд┐рдиреНрди рдХрд╛рд░реНрдпреЛрдВ рдкрд░ рдпрд╣ рддреБрд▓рдирд╛ рдХреА рд╣реИ рдФрд░, рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдпрджрд┐ рд╕реБрдВрдмрд╛ рдХреБрдЫ рдЧрддрд┐ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдЧрддрд┐ рд╕реА рдХреЗ рд╕рд╛рде рддреНрд░реБрдЯрд┐ рд╕реАрдорд╛рдВрдХрди рдХреЗ рдПрдХ рдЧрддрд┐ рдХреЗ рднреАрддрд░ рдЗрд╕реЗ рдЧрддрд┐ рджреЗрддрд╛ рд╣реИ (рдХреЛрдбрд╛рдВрддрд░рдХ рдЖрд╡реЗрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛)ред
рдореИрдВ рджреЛрд╣рд░рд╛рддрд╛ рд╣реВрдВ рдХрд┐ рдпрджрд┐ рдЖрдк рдУрд╣ рд╕реЗ C рдореЗрдВ рдХреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рддреЗ рд╣реИрдВ , рддреЛ рдпрд╣ рдзреАрдореА C / C ++ рд╕реНрдерд┐рддрд┐ рдмрджрд▓ рд╕рдХрддреА рд╣реИред
рдореБрдЭреЗ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдФрд░ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд╕реБрдирдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛрдЧреАред
PS рдЬрдм рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдкрдВрдХреНрддрд┐рдпреЛрдВ / рд╕реНрддрдВрднреЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реЛрддрд╛ рд╣реИ:
рддрд╛рдХрд┐ рд╕реБрдВрдмрд╛ 'C' (si) рдЗрд╕ рдпрд╛ 'A' (si / рдлреЛрд░рдЯреНрд░рд╛рди рдСрдЯреЛ-рд░рд┐рдХрдЧреНрдирд┐рд╢рди) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рди рд╕реЛрдЪреЗрдВ - рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдпрд╣ рдПрдХ рдЖрдпрд╛рдореА рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рднреА рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рд▓рд┐рдП рдЗрд╕ рддрд░рд╣ рдХрд╛ рдПрдХ рдореВрд▓ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╣реИ: uint8[:,:]
рдЗрд╕ ' A '(рдСрдЯреЛ рдбрд┐рдЯреЗрдХреНрд╢рди), nb.uint8[:, ::1]
' C '(si), np.uint8[::1, :]
' F '(рдлреЛрд░рдЯреНрд░рд╛рди) рд╣реИред
@njit(nb.int64(nb.uint8[::1], nb.uint8[::1])) def lev_dist(s1, s2):