рдХреБрдЫ рд╕рдордп рдкрд╣рд▓реЗ, рдореЗрд░реЗ рд╕рд╣рдпреЛрдЧреА рдиреЗ рдореБрдЭреЗ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рд╛рде рдЙрд╕рдХреА рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛ред рдореИрдВрдиреЗ рдЙрд╕рдХреЗ рд▓рд┐рдП рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореБрдЭреЗ рдпрд╣ рдкреНрд░рддреАрдд рд╣реБрдЖ рдХрд┐ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдкрд░, рдХрдИ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдФрд░ рддрдХрдиреАрдХреЛрдВ рдХреЛ рд╕рдордЭрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдФрд░ 25 рд╕реЗрдХрдВрдб рд╕реЗ 40 рдПрдордПрд╕ рддрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордп рдХреЗ рддреНрд╡рд░рдг рдХреЛ рднреА рджрд┐рдЦрд╛рддреЗ рд╣реИрдВред
рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдмрдпрд╛рди
рдПрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП, рдореЗрд░реЗ рд╕рд╣рдпреЛрдЧреА рдХреЛ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рд╡реАрдбрд┐рдпреЛ рдХреЗ рд▓рд┐рдП рдкрдЪрд╛рд╕ рд╕рдорд╛рди рд╡реАрдбрд┐рдпреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереАред рдорд┐рд▓рд╛рди рдХрд┐рдП рдЧрдП рдЯреИрдЧ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рд╕рдорд╛рдирддрд╛ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдерд╛ред рд╡реАрдбрд┐рдпреЛ рдЬрд┐рддрдиреЗ рдЯреИрдЧреНрд╕ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ, рд╡реЗ рдЙрддрдиреЗ рд╣реА рдорд┐рд▓рддреЗ-рдЬреБрд▓рддреЗ рд╣реИрдВред рдЗрд╕рд╕реЗ рд╣рдо рддреБрд░рдВрдд рдХрдИ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ:
- рд╡реАрдбрд┐рдпреЛ рдХреЗ рддрд╣рдд рд╕рднреА рдЯреИрдЧ рдХреЛ рдПрдХ рд╕рдореВрд╣ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ;
- рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╡реАрдбрд┐рдпреЛ рд╕реЗ рдЕрдзрд┐рдХ рдРрд╕реЗ рд╕рдореВрд╣ рдирд╣реАрдВ рд╣реЛрдВрдЧреЗ;
- рдпрджрд┐ рд╡реАрдбрд┐рдпреЛ рдЯреИрдЧ рдХреЗ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдореВрд╣ рдХреЗ рдЕрдиреНрдп рд╡реАрдбрд┐рдпреЛ рдХреЗ рд╕рдорд╛рди рд╣реИ, рддреЛ рдпрд╣ рдЗрд╕ рд╕рдореВрд╣ рдХреЗ рдЕрдиреНрдп рд╡реАрдбрд┐рдпреЛ рдХреЗ рд╕рдорд╛рди рд╣реИ;
рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ рдЯреИрдЧ рд╕рдореВрд╣реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рдПрдХ рд╕рд╣рдХрд░реНрдореА рдиреЗ рдЯреИрдЧ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдЯреИрдЧ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛: рдкреНрд░рддреНрдпреЗрдХ рд╡реАрдбрд┐рдпреЛ рдореЗрдВ рдЯреИрдЧ рд╕рдореВрд╣ рдЖрдИрдбреА рдХрд╛ рдПрдХ рд▓рд┐рдВрдХ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рд╕рдореВрд╣ рд╕реНрд╡рдпрдВ рдмреВрд▓рд┐рдпрди рдорд╛рдиреЛрдВ рдХрд╛ рдПрдХ рдХреНрд░рдо рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд╕рдВрдмрдВрдзрд┐рдд рдЯреИрдЧ рд╕реЗрдЯ рд╣реИ рдпрд╛ рдирд╣реАрдВред C # рдореЗрдВ, рдПрдХ рдЯреИрдЧ рд╕рдореВрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
public class TagsGroup { bool[] InnerTags { get; } }
рдПрдХ рд╕рд╣рдХрд░реНрдореА рдиреЗ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ рдХрд┐ рд╕рд╛рдЗрдЯ рдкрд░ рдЙрд╕рдХреЗ рдкрд╛рд╕ рдПрдХ рдорд┐рд▓рд┐рдпрди рд╕реЗ рдЕрдзрд┐рдХ рд╡реАрдбрд┐рдпреЛ рдирд╣реАрдВ рд╣реЛрдВрдЧреЗ, рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдЯреИрдЧ 4000 рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реИрдВ, рдПрдХ рдЧреЛрд▓ рдЦрд╛рддреЗ рдХреЗ рд▓рд┐рдП рдЖрдк 4096 = 2 ^ 12 рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВред
рдлрд┐рд░ рдЗрд╕ рддрд░рд╣ рд╕реЗ TagsGroup
рд╡рд░реНрдЧ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
public class TagsGroup { public const int TagsGroupLength = 4096; bool[] InnerTags { get; } public TagsGroup(bool[] innerTags) { if (innerTags == null) throw new ArgumentException(nameof(innerTags)); if (innerTags.Length != TagsGroupLength) { throw new ArgumentException(nameof(innerTags)); } InnerTags = innerTags; } }
рдЕрдм рдЖрдкрдХреЛ рд╕рдорд╛рдирддрд╛ рдХреЗ рд▓рд┐рдП рдЯреИрдЧ рдХреЗ рджреЛ рд╕рдореВрд╣реЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЗ рддрд╣рдд, рдпрд╣ рдЯреИрдЧ рдХреЗ рджреЛ рд╕рдореВрд╣реЛрдВ рдХреЗ InnerTags
рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд╕рдВрдмрдВрдзрд┐рдд рддрддреНрд╡реЛрдВ рдореЗрдВ рд╕рдЪ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдЬрд╛рдВрдЪ рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ:
public static int MeasureSimilarity(TagsGroup a, TagsGroup b) { int result = 0; for (int i = 0; i < TagsGroupLength; i++) { if (a.InnerTags[i] && a.InnerTags[i] == b.InnerTags[i]) result++; } return result; }
рдЕрдм рдпрд╣ рдХреЗрд╡рд▓ рдкреНрд░рддреНрдпреЗрдХ рдореМрдЬреВрджрд╛ рд╕рдореВрд╣ рдХреЗ рд╕рд╛рде рд╡рд╛рдВрдЫрд┐рдд рдЯреИрдЧ рд╕рдореВрд╣ рдХреА рд╕рдорд╛рдирддрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдФрд░ рдХреЗрд╡рд▓ рдкрдЪрд╛рд╕ рд╕рдорд╛рди рд▓реЛрдЧреЛрдВ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред рдореИрдВрдиреЗ рдирдореВрдиреЗ рдХреА рд╕реНрдерд┐рд░рддрд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЦреБрдж рдХреЛ рдПрдХ рдФрд░ рд╢рд░реНрдд рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреА, рдЕрд░реНрдерд╛рддреНред рдЕрдВрддрд┐рдо рдирдореВрдиреЗ рдореЗрдВ, рдкрдЪрд╛рд╕ рдЯреИрдЧ рд╕рдореВрд╣ рд╣реЛрдВрдЧреЗ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП MeasureSimilarity
рдиреЗ рдЙрдЪреНрдЪрддрдо рдкрд░рд┐рдгрд╛рдо рджрд┐рдпрд╛, рдЬрдмрдХрд┐ рд╕рдорд╛рди MeasureSimilarity
рдЯреИрдЧ рд╕рдореВрд╣реЛрдВ рдХреЗ MeasureSimilarity
рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП MeasureSimilarity
рдХрдо рд╕реВрдЪрдХрд╛рдВрдХ MeasureSimilarity
рдЬрд┐рдирдХреЗ рдкрд╛рд╕ рдореВрд▓ рдореМрдЬреВрджрд╛ рд╕рдореВрд╣ рдореЗрдВ рдХрдо рд╕реВрдЪрдХрд╛рдВрдХ рдерд╛ред рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣рд╛рдБ: https://ru.wikipedia.org/wiki/Sistentable_Sort ред
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЗрд╕реА рддрд░рд╣ рдХреЗ SimilarTagsCalculator
рдХреНрд▓рд╛рд╕ рдмрдирд╛рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рдпрд╣рд╛рдБ рдЗрд╕рдХрд╛ рдХреЛрдб рд╣реИ:
SimilarTagsCalculator class SimilarTagsCalculator { TagsGroup[] Groups { get; } public SimilarTagsCalculator(TagsGroup[] groups) { if (groups == null) throw new ArgumentException(nameof(groups)); Groups = groups; } public TagsGroup[] GetFiftyMostSimilarGroups(TagsGroup value) { const int resultLength = 50;
рдФрд░ TagsSimilarityInfo
рд╕рдВрд░рдЪрдирд╛:
TagsSimilarityInfo struct TagsSimilarityInfo : IComparable<TagsSimilarityInfo>, IComparable { public int Index { get; } public int Similarity { get; } public TagsSimilarityInfo(int index, int similarity) { Index = index; Similarity = similarity; } public bool Equals(TagsSimilarityInfo other) { return Index == other.Index && Similarity == other.Similarity; } public override bool Equals(object obj) { return obj is TagsSimilarityInfo other && Equals(other); } public override int GetHashCode() { unchecked { return (Index * 397) ^ Similarity; } } public int CompareTo(TagsSimilarityInfo other) { int similarityComparison = other.Similarity.CompareTo(Similarity); return similarityComparison != 0 ? similarityComparison : Index.CompareTo(other.Index); } public int CompareTo(object obj) { if (ReferenceEquals(null, obj)) return 1; return obj is TagsSimilarityInfo other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(TagsSimilarityInfo)}"); } }
рдореИрдВрдиреЗ рдЗрд╕ рдПрд▓реНрдЧреЛрд░рд┐рдердо рдХреЗ рд▓рд┐рдП рддреАрди рдмреЗрдВрдЪрдорд╛рд░реНрдХ рддреИрдпрд╛рд░ рдХрд┐рдП:
- рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдмреЗрдВрдЪрдорд╛рд░реНрдХ, рдЕрд░реНрдерд╛рддреНред рд╕рдореВрд╣реЛрдВ рдореЗрдВ рд╕реЗрдЯ рдЯреИрдЧ рдХреА рд╕рдВрдЦреНрдпрд╛ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╣реИ рдФрд░ рдЯреИрдЧ рд╕рдореВрд╣ рдЬрд┐рд╕рдХреА рд╣рдо рддреБрд▓рдирд╛ рдХрд░реЗрдВрдЧреЗ, рд╡рд╣ рднреА рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╣реИ;
- рд╕рдореВрд╣реЛрдВ рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдП рдЧрдП рдЯреИрдЧ рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрдврд╝ рд░рд╣реА рд╣реИ, рд╣рдо рдЙрд╕ рд╕рдореВрд╣ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░реЗрдВрдЧреЗ рдЬрд┐рд╕рдореЗрдВ рд╕рднреА рдЯреИрдЧ рд╕реЗрдЯ рд╣реИрдВред рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдЯреИрдЧ рдХреЗ рдЕрдВрддрд┐рдо рд╕рдореВрд╣реЛрдВ рдореЗрдВ рд╕реЗ рдХреБрдЫ рд╕рдмрд╕реЗ рдЙрдкрдпреБрдХреНрдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП;
- рдКрдкрд░ рдЬреИрд╕рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрдЬрд╛рдЧрд░ рдЯреИрдЧ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХрдо рд╣реЛ рд░рд╣реА рд╣реИред рдЯреИрдЧ рдХреЗ рдкрд╣рд▓реЗ 50 рд╕рдореВрд╣ рд╕рдмрд╕реЗ рдЙрдкрдпреБрдХреНрдд рд╣реЛрдВрдЧреЗ;
рдпрд╣рд╛рдВ рдПрдХ рд▓рд╛рдЦ рд╕рдореВрд╣реЛрдВ рдХреЗ рд▓рд┐рдП рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдкрд░рд┐рдгрд╛рдо рд╣реИрдВ:
рдмреЗрдВрдЪрдорд╛рд░реНрдХрдбреЙрдЯрдиреЗрдЯ = v0.11.5, рдУрдПрд╕ = рд╡рд┐рдВрдбреЛрдЬ 10.0.17134.765 (1803 / рдЕрдкреНрд░реИрд▓ 2018 рдпреВрдкреАрдбреЗрдЯ / рд░реЗрдбрд╕реНрдЯреЛрди 4)
Intel Core i7-6700 CPU 3.40GHz (Skylake), 1 CPU, 8 рддрд╛рд░реНрдХрд┐рдХ рдФрд░ 4 рднреМрддрд┐рдХ рдХреЛрд░
рдлреНрд░реАрдХреНрд╡реЗрдВрд╕реА = 3328126 рд╣рд░реНрдЯреНрдЬ, рд░рд┐рдЬрд╝реЙрд▓реНрдпреВрд╢рди = 300.4694 рдПрдирдПрд╕, рдЯрд╛рдЗрдорд░ = рдЯреАрдПрд╕рд╕реА
.NET рдХреЛрд░ рдПрд╕рдбреАрдХреЗ = 3.0.100-рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди 5-011568
[рд╣реЛрд╕реНрдЯ]: .NET рдХреЛрд░ 3.0.0-рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди 5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64 рдмрд┐рдЯ RyuJIT
рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордп рдХрд╛ рдкреНрд░рд╕рд╛рд░ рдмрд╣реБрдд рдмрдбрд╝рд╛ рд╣реИ, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ 25 рд╕реЗрдХрдВрдб рдмрд╣реБрдд рд▓рдВрдмрд╛ рд╕рдордп рд╣реИ, рдореЗрд░реЗ рд╕рд╣рдпреЛрдЧреА рдЗрддрдиреЗ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдЗрдВрддрдЬрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣рдордд рдирд╣реАрдВ рд╣реИрдВред рддреЛ рдЪрд▓реЛ рдЕрдиреБрдХреВрд▓рди рдХрд░рддреЗ рд╣реИрдВред рдЕрдм рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рддреАрди рдореБрдЦреНрдп рдХреНрд╖реЗрддреНрд░ рд╣реИрдВ:
MeasureSimilarity
;GetFiftyMostSimilarGroups
рдореЗрдВ рдкрд╛рд╢ рдХреЗ рд╢рд░реАрд░ рдореЗрдВ рдПрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо;GetFiftyMostSimilarGroups
рдореЗрдВ рд╕реНрд╡рдпрдВ рд▓реВрдк;
рд╣рдо рдХреНрд░рдо рдореЗрдВ рддреАрди рджрд┐рд╢рд╛рдУрдВ рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред
рд╢рд╛рдЦрд╛ рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, MeasureSimilarity
рд╡рд┐рдзрд┐ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
public static int MeasureSimilarity(TagsGroup a, TagsGroup b) { int result = 0; for (int i = 0; i < TagsGroupLength; i++) { if (a.InnerTags[i] && a.InnerTags[i] == b.InnerTags[i]) result++; } return result; }
рдкрд┐рдЫрд▓реЗ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдореЗрдВ, рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдкрд░реАрдХреНрд╖рдг рдФрд░ рдХреНрд░рдорд┐рдХ рдХрд┐рд╕реА рдХреЗ рдмреАрдЪ рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдмрд╣реБрдд рдмрдбрд╝реА рднрд┐рдиреНрдирддрд╛ рдереАред рдЕрдиреБрдХреНрд░рдорд┐рдХ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдЯреИрдЧ рд╕рдореВрд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд┐рджреНрдзрд╛рдВрдд рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдП рдЧрдП рдереЗ:
- рд╕рдореВрд╣реЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕рдВрдХреБрд▓ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдкреИрдХреЗрдЯ рдХреА рд╕рдВрдЦреНрдпрд╛ - рд╕рдореВрд╣ рдореЗрдВ рдЯреИрдЧ рдХреА рдЕрдзрд┐рдХрддрдо рд╕рдВрдЦреНрдпрд╛;
- i-th рдкреИрдХреЗрдЬ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╕рдореВрд╣ рдХреЗ рд▓рд┐рдП, рдкрд╣рд▓реЗ i рдЯреИрдЧ рд╕реЗрдЯ рдХрд┐рдП рдЧрдП рдереЗ;
рдпрд╣ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдЗрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдЯреИрдЧ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рдореВрд╣ рдореЗрдВ рдЙрдЬрд╛рдЧрд░ рдФрд░ рдЕрдирдПрдореНрдкреЛрдЬрд╝реНрдб рдЯреИрдЧ рдХреЗ рджреЛ рд▓рдЧрд╛рддрд╛рд░ рднрд╛рдЧ рд╣реЛрддреЗ рд╣реИрдВред MeasureSimilarity
рдореЗрдВ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреА рдкреВрд░реНрд╡ рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рд╢рд░реНрддреЗрдВ рд╣реИрдВ рдЬреЛ рд╡рд░реНрддрдорд╛рди рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкреНрд░рднрд╛рд╡ рдбрд╛рд▓рддреА рд╣реИрдВред рдЗрд╕реЗ рдЬрд╛рдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдПрдХ рдорд╛рдирджрдВрдб рд▓рд┐рдЦреЗрдВ, рдЬреЛ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдФрд░ рдЕрдиреБрдХреНрд░рдорд┐рдХ рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдорд╛рдк-рдХреНрд╖рдорддрд╛ рдХреЗ рдХреНрд░рдо рдХреА рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИ:
int GetSimilaritySum(TagsGroup[] tagsGroups) { int result = 0; foreach (TagsGroup tagsGroup in tagsGroups) { result += TagsGroup.MeasureSimilarity(tagsGroup, etalon); } return result; } [Benchmark] public int Sorted() => GetSimilaritySum(sortedGroups); [Benchmark] public int Unsorted() => GetSimilaritySum(unsortedGroups);
рдПрдХ рд▓рд╛рдЦ рдЯреИрдЧ рд╕рдореВрд╣реЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рдореВрд╣ рдореЗрдВ Sorted
рд╕реЗ рдХрдИ рдЙрдЬрд╛рдЧрд░ рдЯреИрдЧ рдереЗ, рдФрд░ рдлрд┐рд░ рдЕрдирдПрдХреНрд╕рдкреЛрдЬрд╝реНрдб рд╡рд╛рд▓реЗ, рдФрд░ Unsorted
рдореЗрдВ рд╕рдорд╛рди рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдЙрдЬрд╛рдЧрд░ рдХрд┐рдП рдЧрдП рдЯреИрдЧ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд░реВрдк рд╕реЗ рдкреВрд░реЗ рд╕рдореВрд╣ рдореЗрдВ рдмрд┐рдЦрд░реЗ рд╣реБрдП рдереЗред
5 рд╕реЗрдХрдВрдб рдХрд╛ рдЕрдВрддрд░ рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рд╣реИ, рдФрд░ рдХреБрдЫ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╢рд╛рдЦрд╛ рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХреЗ рдкреНрд░рднрд╛рд╡ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдЖрдо рддреМрд░ рдкрд░ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЦреБрдж рд╢рд╛рдЦрд╛рдУрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред MeasureSimilarity
рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рд╢рд╛рдЦрд╛ рд╣реИ - рдпрд╣ рдЬрд╛рдВрдЪрдирд╛ рдХрд┐ рд╕рдВрдмрдВрдзрд┐рдд рдЯреИрдЧ рджреЛ рд╕рдореВрд╣реЛрдВ рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдП рдЧрдП рд╣реИрдВред рдЖрдЗрдП рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рди рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рд╕реНрдерд┐рддрд┐ рд╕рд╣реА рд╣реЛрдЧреА, рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рд╕реНрдерд┐рддрд┐ рдХреА рд╕рдЪреНрдЪрд╛рдИ рдХреА рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рдмрдирд╛рдПрдВрдЧреЗ:
рд╕рддреНрдп рддрд╛рд▓рд┐рдХрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддрд╛рд░реНрдХрд┐рдХ "рдФрд░" рдХреЗ рд╕рд╛рде рдореЗрд▓ рдЦрд╛рддреА рд╣реИ, рдЕрд░реНрдерд╛рддред рдкрд░рд┐рдгрд╛рдо рд╕рд╣реА рд╣реИ рдЕрдЧрд░ рдФрд░ рдХреЗрд╡рд▓ рдпрджрд┐ рджреЛрдиреЛрдВ рдЯреИрдЧ рд╕рддреНрдп рд╣реИрдВ, рддреЛ рд╕реНрдерд┐рддрд┐ рдХреЛ рдХрдо рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: if (a.InnerTags[i] && b.InnerTags[i])
ред рд▓реЗрдХрд┐рди рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╣рд╛рд▓рдд рдЕрднреА рднреА рдмрдиреА рд╣реБрдИ рд╣реИред рдЕрдЧрд▓реЗ рдЪрд░рдг рдореЗрдВ, рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рд╡реГрджреНрдзрд┐ рд╣рдореЗрд╢рд╛ рдХреА рдЬрд╛рддреА рд╣реИ, рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рд▓реВрдк рдХреЗ рд╢рд░реАрд░ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬреИрд╕реЗ:
int t = a.InnerTags[i] && b.InnerTags[i] ? 1 : 0; result += t;
рд╣рдордиреЗ рдЕрднреА рднреА рд╣рд╛рд▓рдд рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдирд╣реАрдВ рдкрд╛рдпрд╛ рд╣реИ рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рднреА рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдзреАрдорд╛ рдХрд░ рджрд┐рдпрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдм рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдЕрдЧрд░ InnerTags
рдкреНрд░рдХрд╛рд░ рдмреВрд▓ рд╕реЗ рдмрд╛рдЗрдЯ рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ (рд╕рдЪ рдХреЗ рд▓рд┐рдП 1, рдФрд░ рдЧрд▓рдд рдХреЗ рд▓рд┐рдП 0), рддреЛ рдЖрдк рдЯрд░реНрдирд░реА рдСрдкрд░реЗрдЯрд░ рдореЗрдВ рд╕реНрдерд┐рддрд┐ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред рддрдм TagsGroup
рдХреНрд▓рд╛рд╕ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧреА:
TagsGroup public class TagsGroup { public const int TagsGroupLength = 4096; byte[] InnerTags { get; } public static int MeasureSimilarity(TagsGroup a, TagsGroup b) { int result = 0; for (int i = 0; i < TagsGroupLength; i++) { int t = a.InnerTags[i] & b.InnerTags[i]; result += t; } return result; } public TagsGroup(bool[] innerTags) { if (innerTags == null) throw new ArgumentException(nameof(innerTags)); if (innerTags.Length != TagsGroupLength) { throw new ArgumentException(nameof(innerTags)); } InnerTags = new byte[TagsGroupLength]; for (int i = 0; i < TagsGroupLength; i++) { InnerTags[i] = (byte) (innerTags[i] ? 1 : 0); } } }
рдпрд╣рд╛рдБ рдЕрджреНрдпрддрди MeasureSimilarity
рд▓рд┐рдП рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдкрд░рд┐рдгрд╛рдо рд╣реИрдВ:
рд▓реЗрдХрд┐рди рдЕрджреНрдпрддрди рдХрд┐рдП рдЧрдП рдореБрдЦреНрдп рдмреАрдЪрдорд╛рд░реНрдХ рдХреЗ рд▓рд┐рдП:
рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдерд╛ред рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЖрд╢реНрд╡рд╕реНрдд рдереЗ рдХрд┐ рд╕рднреА рддреНрд╡рд░рдг рдХреЗрд╡рд▓ рдЗрд╕рд▓рд┐рдП рд╣реБрдП рдХреНрдпреЛрдВрдХрд┐ рдмреВрд▓рд┐рдпрди рдкреНрд░рдХрд╛рд░ рдХреЛ рдмрд╛рдЗрдЯ рдХреЗ рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдореИрдВрдиреЗ рдРрд╕реЗ рд▓реВрдк рдмреЙрдбреА рдХреЗ рд▓рд┐рдП рдПрдХ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛:
int t = a.InnerTags[i] & b.InnerTags[i]; if (t == 1) result += t;
рдФрд░ рдпреЗ рдкрд░рд┐рдгрд╛рдо рд╣реИрдВ:
рдбреЗрдЯрд╛ рдкреИрдХреЗрдЬрд┐рдВрдЧ
рдкреНрд░рддреНрдпреЗрдХ рд╕рдореВрд╣ рдХреЗ рдХрдИ рдЯреИрдЧ рд╣реИрдВ, рдФрд░ рдЙрдирдХреА рд╕рдВрдЦреНрдпрд╛ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдХрдо рдирд╣реАрдВ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ рдПрдХ рд╣реА рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд╕рд╛рде рдЯреИрдЧреНрд╕ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЖрдк рд╕рднреА рдЯреИрдЧреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд┐рдП рдмрд┐рдирд╛ рдЕрдВрддрд┐рдо рдЬрд╡рд╛рдм рдирд╣реАрдВ рджреЗ рд╕рдХрддреЗред рдЗрд╕рд▓рд┐рдП, рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдореЗрдВ рдЯреИрдЧ рдХреЗ рдкреВрд░реЗ рд╕рдореВрд╣ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░рдиреА рд╣реЛрдЧреАред рдЗрд╕ рдХрд╛рд░реНрдп рдХреЛ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рд╕рдорд╛рдирд╛рдВрддрд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛, рддрд╛рдХрд┐ рдПрдХ рд╕рд╢рд░реНрдд рд╕рдВрдЪрд╛рд▓рди рдореЗрдВ рдХрдИ рдЯреИрдЧ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред рдЖрдк рдЗрд╕реЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдорд╛рдирд╛рдВрддрд░рдХрд░рдг рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдЖрдк рд╡рд┐рд╢реЗрд╖ рдбреЗрдЯрд╛ рдкреИрдХреЗрдЬрд┐рдВрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рд╣рдо рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдкреНрд░рддреНрдпреЗрдХ рдЯреИрдЧ рдЕрдм 1 рдпрд╛ 0. рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИред рдкрд░рд┐рдгрд╛рдо рдореЗрдВ, рдСрдкрд░реЗрд╢рди "AND" рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдХреЗрд╡рд▓ рдЬрдорд╛ рд╣реЛрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдПрдХ рд╣реА рддрд╛рд░реНрдХрд┐рдХ рд╕рдВрдЪрд╛рд▓рди рди рдХреЗрд╡рд▓ рдПрдХрд▓-рдмрд┐рдЯ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдкрд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред C # рдЖрдкрдХреЛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ 64 рдмрд┐рдЯ рдирдВрдмрд░ рддрдХ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ (рдЖрдк BitArray
рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдзрд┐рдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдирд╣реАрдВ рд╣реИ)ред рдпрджрд┐ рд╣рдо рд╕рдВрдмрдВрдзрд┐рдд рдмрд┐рдЯреНрд╕ рдХреЗ рд╕реЗрдЯ рдХреЗ рд╕рд╛рде 64 рдмрд┐рдЯ рдирдВрдмрд░реЛрдВ рдХреЗ рд╕рдореВрд╣ рдХреЗ рд░реВрдк рдореЗрдВ рдЯреИрдЧ рдХреЗ рджреЛ рд╕рдореВрд╣реЛрдВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ 64 рдмрд┐рдЯ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рдРрд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рдореВрд╣ рдкрд░ рдПрдХ "рдФрд░" рдСрдкрд░реЗрд╢рди рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдкрд░рд┐рдгрд╛рдо рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИред рдЖрдЗрдП рдлрд┐рд░ рд╕реЗ рд▓реВрдк рдХреЗ рд╢рд░реАрд░ рдкрд░ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
int t = a.InnerTags[i] & b.InnerTags[i]; result += t;
рдкрд░рд┐рдгрд╛рдо 1 рд╣рд░ рдмрд╛рд░ t == 1 рд╕реЗ рдмрдврд╝рддрд╛ рд╣реИ рдФрд░ рдЬрдм t == 0. рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ, рддреЛ рдкрд░рд┐рдгрд╛рдо рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рдХрд┐рддрдиреЗ рдмрд╛рд░ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдЧрд╛ред a.InnerTags[i] & b.InnerTags[i]
рдПрдХ рдерд╛ред рддрджрдиреБрд╕рд╛рд░, рдХрд┐рд╕реА рд╕рд░рдгреА рдореЗрдВ a.InnerTags[i] & b.InnerTags[i]
рд╕рднреА рдкрд░рд┐рдгрд╛рдо рд╕рд╣реЗрдЬрдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛, рдФрд░ рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рдЗрд╕ рд╕рд░рдгреА рдореЗрдВ рдХреЗрд╡рд▓ рдЗрдХрд╛рдЗрдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд▓рд┐рдЦреЗрдВред рдПрди-рдмрд┐рдЯ рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рдЕрдзрд┐рдХ рдкрд░ рдПрдВрдб рдСрдкрд░реЗрд╢рди рдХрд░рддреЗ рд╕рдордп, рдПрдХ рдПрди-рдмрд┐рдЯ рдкрд░рд┐рдгрд╛рдо рд╣реЛрдЧрд╛ рдФрд░ рдпрд╣ рдХреЗрд╡рд▓ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдЧрд╛ рдХрд┐ рдПрди рдХреЗ рдмреАрдЪ рдХрд┐рддрдиреЗ рдмрд┐рдЯ рд╕реЗрдЯ рд╣реИрдВред рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╕реЗрдЯ рдмрд┐рдЯреНрд╕ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдЖрдк рдЗрди рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдЧрд┐рди рд╕рдХрддреЗ рд╣реИрдВред 64 рдмрд┐рдЯреНрд╕ рдХреА рдЧрд┐рдирддреА рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдореЗрдВ рдЗрддрдиреА рд░реИрдо рдирд╣реАрдВ рдорд┐рд▓реЗрдЧреАред 32 рдмрд┐рдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЖрдзреБрдирд┐рдХ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рдЬрдЧрд╣ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрднреА рднреА рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИред 16 рдмрд┐рдЯреНрд╕ рдХреЗ рддрд╣рдд рдореЗрдореЛрд░реА рдХреЛ рдвреВрдВрдврдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЧрдгрдирд╛ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд▓рдВрдмреА рд╣реЛрдЧреАред рдПрдХ рд╕рдордЭреМрддреЗ рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдЗрдП 8 рдмрд┐рдЯ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЧрдгрдирд╛ рдХрд░реЗрдВ:
GenerateCountOfSettedBits static readonly byte[] CountOfSettedBits = GenerateCountOfSettedBits(); static byte[] GenerateCountOfSettedBits() {
рдЕрдм рдЯреИрдЧрдЧреНрд░реБрдк рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
const int BucketSize = 8; public TagsGroup(bool[] innerTags) { if (innerTags == null) throw new ArgumentException(nameof(innerTags)); if (innerTags.Length != TagsGroupLength) { throw new ArgumentException(nameof(innerTags)); } int index = 0;
рдФрд░ MeasureSimilarity
рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдирд╛ рд╢реБрд░реВ рд╣реБрдИ:
public static int MeasureSimilarity(TagsGroup a, TagsGroup b) { int result = 0; for (int i = 0; i < TagsGroupLength / BucketSize; i++) { int t = a.InnerTags[i] & b.InnerTags[i]; result += CountOfSettedBits[t]; } return result; }
рдЖрдк рдПрдХ рдмрдбрд╝рд╛ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╕рдм рдХреБрдЫ рдмреЗрд╣рддрд░ рд╣реИ:
рдХреНрдпрд╛ MeasureSimilarity
рд╡рд┐рдзрд┐ рдХреЛ рдФрд░ рднреА рддреЗрдЬ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ? рдмреЗрд╢рдХ! рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреЛ рдорд╣рд╕реВрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рдХрд┐ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдпреЛрдЬрди рд░рдЬрд┐рд╕реНрдЯрд░ рдЕрдм рдЬреНрдпрд╛рджрд╛рддрд░ 64 рдмрд┐рдЯ рд╣реИрдВ, рдФрд░ рд╣рдо рдЙрдирдореЗрдВ рдЖрда-рдмрд┐рдЯ рдбреЗрдЯрд╛ рдЪрд▓рд╛рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдкреИрдХреЗрдЯ рдХрд╛ рдЖрдХрд╛рд░ рдмрдврд╝рд╛рдПрдВ рдЬрд┐рд╕рдореЗрдВ рдореВрд▓ рдЯреИрдЧ рдкреИрдХ рдХрд┐рдП рдЧрдП рд╣реЛрдВ, 64 рдмрд┐рдЯ рддрдХ рдмрдврд╝реЗрдВ рдФрд░ рдЖрд╡рд╢реНрдпрдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреЗрдВ:
const int BucketSize = 64; ulong[] InnerTags { get; } public static int MeasureSimilarity(TagsGroup a, TagsGroup b) { int result = 0; for (int i = 0; i < TagsGroupLength / BucketSize; i++) { ulong t = a.InnerTags[i] & b.InnerTags[i]; for (int j = 0; j < BucketSize / 8; j++) { result += CountOfSettedBits[t & 255]; t >>= 8; } } return result; }
рдФрд░ рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ:
рдлрд┐рд░ рдЖрдк рдЖрдВрддрд░рд┐рдХ рд▓реВрдк рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
MeasureSimilarity public static int MeasureSimilarity(TagsGroup a, TagsGroup b) { int result = 0; for (int i = 0; i < TagsGroupLength / BucketSize; i++) { ulong t = a.InnerTags[i] & b.InnerTags[i]; result += CountOfSettedBits[t & 255]; t >>= 8; result += CountOfSettedBits[t & 255]; t >>= 8; result += CountOfSettedBits[t & 255]; t >>= 8; result += CountOfSettedBits[t & 255]; t >>= 8; result += CountOfSettedBits[t & 255]; t >>= 8; result += CountOfSettedBits[t & 255]; t >>= 8; result += CountOfSettedBits[t & 255]; t >>= 8; result += CountOfSettedBits[t & 255]; } return result; }
рдХреНрдпрд╛ рдпрд╣ рдФрд░ рднреА рддреЗрдЬ рд╣реИ? рд╣рд╛рдБ! рдпрджрд┐ рдЖрдк .NET рдХреЛрд░ 3.0 рд╕реЗ рдирд╡рд╛рдЪрд╛рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рд╕рдВрд╕реНрдХрд░рдг рдЕрднреА рднреА рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдореЗрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╢реБрд░реБрдЖрдд рд╕реЗ рд╣реА рдХреБрдЫ рдЖрдВрддрд░рд┐рдХ рд╡рд┐рд╖рдпреЛрдВ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред рдЗрдВрдЯреЗрд▓ рдЖрдВрддрд░рд┐рдХ рдЧрд╛рдЗрдб рдореЗрдВ рдЖрдВрддрд░рд┐рдХ _mm_popcnt_u64
ред рдЬреИрд╕рд╛ рдХрд┐ рд╡рд░реНрдгрд┐рдд рд╣реИ: " рдЕрд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд 64-рдмрд┐рдЯ рдкреВрд░реНрдгрд╛рдВрдХ рдореЗрдВ 1 рдореЗрдВ рд╕реЗрдЯ рдмрд┐рдЯреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВ, рдФрд░ рдЙрд╕ dst рдореЗрдВ рд▓реМрдЯреЗрдВред " рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдо рдХреНрдпрд╛ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ! .NET Core 3.0 рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди 5 рдореЗрдВ, рдпрд╣ рдЖрдВрддрд░рд┐рдХ System.Runtime.Intrinsics.X86.Popcnt.X64.IsSupported
System.Runtime.Intrinsics.X86.Popcnt.X64.PopCount
рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (рдЬреИрд╕рд╛ рдХрд┐ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдПрдХ tk рдХреА рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЖрдкрдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдкреНрд░реЛрд╕реЗрд╕рд░ рдЖрдВрддрд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЙрдирдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, System.Runtime.Intrinsics.X86.Popcnt.X64.IsSupported
рд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВред System.Runtime.Intrinsics.X86.Popcnt.X64.IsSupported
)ред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, MeasureSimilarity
рд╡рд┐рдзрд┐ рдХрд╛ рдХреЛрдб рдЗрд╕ рддрд░рд╣ рдмрди рдЬрд╛рдПрдЧрд╛:
public static int MeasureSimilarity(TagsGroup a, TagsGroup b) { int result = 0; for (int i = 0; i < TagsGroupLength / BucketSize; i++) { ulong t = a.InnerTags[i] & b.InnerTags[i]; result += (int) System.Runtime.Intrinsics.X86.Popcnt.X64.PopCount(t); } return result; }
рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордп:
рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реАред
рдореБрдЭреЗ рдЙрди рддрд░реАрдХреЛрдВ рдХреА рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВ рд╣реИ, рдЬреЛ MeasureSimilarity
рдХрд╛рдлреА рддреЗрдЬреА рд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕рд╛рде рд╣реА рд╕рд╛рде рдкрдардиреАрдпрддрд╛ рдХреЛ рдмрд╣реБрдд рдЦрд░рд╛рдм рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдВ
рдЕрдм рд╣рдо GetFiftyMostSimilarGroups
рд╡рд┐рдзрд┐ рдореЗрдВ рд▓реВрдк рдХреЗ рд╢рд░реАрд░ рдХреЗ рд╕рд╛рде GetFiftyMostSimilarGroups
рдХрд░реЗрдВрдЧреЗ:
GetFiftyMostSimilarGroups public TagsGroup[] GetFiftyMostSimilarGroups(TagsGroup value) { const int resultLength = 50; List<TagsSimilarityInfo> list = new List<TagsSimilarityInfo>(50); for (int groupIndex = 0; groupIndex < Groups.Length; groupIndex++) { TagsGroup tagsGroup = Groups[groupIndex]; int similarityValue = TagsGroup.MeasureSimilarity(value, tagsGroup); TagsSimilarityInfo newInfo = new TagsSimilarityInfo(groupIndex, similarityValue); if (list.Count == resultLength && list[resultLength - 1].CompareTo(newInfo) == -1) { continue; } int index = ~list.BinarySearch(newInfo); list.Insert(index, newInfo); if (list.Count > resultLength) { list.RemoveAt(resultLength); } } TagsGroup[] result = new TagsGroup[resultLength]; for (int i = 0; i < resultLength; i++) { result[i] = Groups[list[i].Index]; } return result; }
рдореБрдЭреЗ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдпрд╛рдж рджрд┐рд▓рд╛рдПрдВ рдХрд┐ рдпрд╣рд╛рдВ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ:
- рд╕реВрдЪреА рдХреЗ рдЕрдВрджрд░, рдкрдЪрд╛рд╕ рд╕рдмрд╕реЗ рдЙрдкрдпреБрдХреНрдд рдЯреИрдЧ рд╕рдореВрд╣реЛрдВ рдХреА рдПрдХ рдХреНрд░рдордмрджреНрдз рд╕реВрдЪреА рд╕рдВрдЧреНрд░рд╣реАрдд рдХреА рдЬрд╛рддреА рд╣реИ, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЫреЛрдЯреЗ рд╕реЗ рдмрдбрд╝реЗ рддрдХ, рдпрджрд┐ рдЖрдк
TagsSimilarityInfo
рддреБрд▓рдирд╛ TagsSimilarityInfo
; - рдЫрдБрдЯрд╛рдИ рдХреЛ рд╕рдВрд░рдХреНрд╖рд┐рдд рдХрд░рддреЗ рд╣реБрдП рд╕реВрдЪреА рдореЗрдВ рдирдП рд╕рдореВрд╣ рдХреЛ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░реЗрдВ;
- рдпрджрд┐ рд╕реВрдЪреА рдореЗрдВ рдкрдЪрд╛рд╕ рд╕реЗ рдЕрдзрд┐рдХ рддрддреНрд╡ рд╣реИрдВ, рддреЛ рдХрдо рд╕реЗ рдХрдо рд╕рдорд╛рди рд╕рдореВрд╣ рдХреЛ рд╣рдЯрд╛ рджреЗрдВ (рдЗрд╕рдХреА рдЬрд╛рдирдХрд╛рд░реА-рд╡рд╕реНрддреБ рд╕рдмрд╕реЗ рдмрдбрд╝реА рд╣реЛрдЧреА рдФрд░
list
рдХреЗ рдмрд╣реБрдд рдЕрдВрдд рдореЗрдВ рд╣реЛрдЧреА);
рдпрд╛рдиреА рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рд╕рдмрд╕реЗ рдмрдбрд╝рд╛ рддрддреНрд╡ рдЦреЛрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд▓реНрджреА рд╕реЗ рдбрд╛рд▓рдиреЗ рдФрд░ рд╣рдЯрд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛред рдРрд╕реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рд┐рд╢реЗрд╖ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдВ рд╣реИрдВред рдкрд╣рд▓реА рдмрд╛рдд рдЬреЛ рдорди рдореЗрдВ рдЖрддреА рд╣реИ рд╡рд╣ рд╣реИ рдПрдХ рдЧреБрдЪреНрдЫрд╛ ред рдЙрд╕рдХреА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ O (рд▓реЙрдЧ рдПрди) рдореЗрдВ рдХреА рдЬрд╛рддреА рд╣реИ, рдУ (1 рдПрди) рдореЗрдВ рдПрдХ рддрддреНрд╡ рдХреЛ рд╣рдЯрд╛рддреЗ рд╣реБрдП, рдУ (1) рдореЗрдВ рдЕрдзрд┐рдХрддрдо рд╣реЛ рд░рд╣реА рд╣реИред рдПрдХрдорд╛рддреНрд░ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдвреЗрд░ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдП рдмрд┐рдирд╛ рдмрдврд╝рддреЗ рддрддреНрд╡реЛрдВ рджреНрд╡рд╛рд░рд╛ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред BCL рдореЗрдВ рдХреЛрдИ рдмрд╛рдЗрдирд░реА рд╣реАрдк рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рд▓рд┐рдЦрд╛:
BinaryHeap public class BinaryHeap<T>:IEnumerable<T> where T : IComparable<T> { readonly List<T> innerList; public BinaryHeap(int capacity) { innerList = new List<T>(capacity); } public int Count => innerList.Count; public T Max => innerList[0]; public void Add(T value) { innerList.Add(value); int i = Count - 1; int parent = (i - 1) >> 1; while (i > 0 && innerList[parent].CompareTo(innerList[i]) == -1) { Swap(i, parent); i = parent; parent = (i - 1) >> 1; } } void Swap(int a, int b) { T temp = innerList[a]; innerList[a] = innerList[b]; innerList[b] = temp; } void Heapify(int i) { for (;;) { int leftChild = (i << 1) | 1; int rightChild = (i + 1) << 1; int largestChild = i; if (leftChild < Count && innerList[leftChild].CompareTo(innerList[largestChild]) == 1) { largestChild = leftChild; } if (rightChild < Count && innerList[rightChild].CompareTo(innerList[largestChild]) == 1) { largestChild = rightChild; } if (largestChild == i) { break; } Swap(i, largestChild); i = largestChild; } } public void RemoveMax() { innerList[0] = innerList[Count - 1]; innerList.RemoveAt(Count - 1); Heapify(0); } public IEnumerator<T> GetEnumerator() { return innerList.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable) innerList).GetEnumerator(); } }
GetFiftyMostSimilarGroups
рд╡рд┐рдзрд┐ рдХрд╛ рд╕рдВрдЧрдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓реЗрдЦ рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб (рдиреАрдЪреЗ рд▓рд┐рдВрдХ) рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдвреЗрд░ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рдмрд╛рдЗрдирд░реА рд╕рд░реНрдЪ рдЯреНрд░реА рдКрдкрд░ рдЖ рд╕рдХрддрд╛ рд╣реИред рдПрдХ рд╕рдВрддреБрд▓рд┐рдд рдмрд╛рдЗрдирд░реА рд╕рд░реНрдЪ рдЯреНрд░реА рдУ (рд▓реЙрдЧ рдПрди) рдХреЗ рд▓рд┐рдП рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдУ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХрддрдо рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ (рд▓реЙрдЧ рдПрди), рдУ (рд▓реЙрдЧ рдПрди) рдХреЗ рд▓рд┐рдП рдПрдХ рддрддреНрд╡ рдХреЛ рд╣рдЯрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рд▓рд╛рдн рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдЖрд░реЛрд╣реА рдХреНрд░рдо рдореЗрдВ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдмреАрд╕реАрдПрд▓ рдореЗрдВ рд▓рд╛рд▓-рдХрд╛рд▓реЗ рд░рдВрдЧ рдХреЗ рдЦреЛрдЬ рдХреЛ рд╕реЙрд░реНрдЯреЗрдбрд╕реЗрдЯ (рдПрдХ рдмрдбрд╝реЗ рдврд╛рдВрдЪреЗ рдореЗрдВ, рдЕрдзрд┐рдХрддрдо .net 3.0 рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдзреАрдореА рдЧрддрд┐ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░ рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдирд╛) рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред GetFiftyMostSimilarGroups
рд▓рд┐рдП GetFiftyMostSimilarGroups рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓реЗрдЦ рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рд╕рднреА рддреАрди GetFiftyMostSimilarGroups
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдкрд░рд┐рдгрд╛рдо:
рдПрдХ рдкрддреНрддреЗ рдХреЗ рд╕рд╛рде рдореВрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рдЧрднрдЧ рд╣рд░ рдЬрдЧрд╣ рд╕рдордп рдореЗрдВ рдЬреАрддрддрд╛ рд╣реИ, рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╣рд░ рдЬрдЧрд╣ рд╕реНрдореГрддрд┐ рдореЗрдВред рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рд╢реАрдЯ рдХреЗ рд╕рд╛рде рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рд▓рд┐рдП, рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдУ (рд▓реЙрдЧ рдПрди) рдореЗрдВ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдбрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рдЧрднрдЧ рдУ (1), рдХреНрдпреЛрдВрдХрд┐ рддрддреНрд╡реЛрдВ рдХреА рдЗрддрдиреА рдХрдо рд╕рдВрдЦреНрдпрд╛ рдХреА рдирдХрд▓ рдХрд░рдирд╛ рдмрд╣реБрдд рдЬрд▓реНрджреА рд╣реЛрддрд╛ рд╣реИ, рдУ (1) рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХрддрдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛, рдУ (1) рдХреЗ рд▓рд┐рдП рднреА рдПрдХ рддрддреНрд╡ рдХреЛ рд╣рдЯрд╛рдирд╛, рдХреНрдпреЛрдВрдХрд┐ , .net, рд╢реАрдЯ рд╕реЗ рдЕрдВрддрд┐рдо рддрддреНрд╡ рдХреЛ рд╣рдЯрд╛рдХрд░ рдЕрдВрддрд┐рдо рддрддреНрд╡ рдХреЛ рдПрдХ рдЦрд╛рд▓реА рдорд╛рди рд▓рд┐рдЦрдХрд░ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЗрди .net рдХреЛрд░ рдХреБрдЫ рднреА рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ) рдпрджрд┐ рдЗрд╕реЗ 50 рдирд╣реАрдВ рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдЪрд▓реЛ 1000 рд╕рдмрд╕реЗ рд╕рдорд╛рди рд╕рдореВрд╣реЛрдВ рдХреЛ рдХрд╣рддреЗ рд╣реИрдВ, рддреЛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ, рд╢реАрдЯ рдХреЗ рд╕рд╛рде рдПрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рд╕рдм рдереЛрдбрд╝рд╛ рд╕рдЯреНрдЯрд╛ рддрд░реНрдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рдЕрднреА рднреА рдкреНрд░рддреНрдпреЗрдХ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ рд╕рдорд╛рдпреЛрдЬрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдмрд╣реБ рд╕реВрддреНрд░рдг
рдЕрдм рдпрд╣ GetFiftyMostSimilarGroups
рдореЗрдВ рдкрд╛рд╢ рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред рдХреЗрд╡рд▓ рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рджрд┐рдорд╛рдЧ рдореЗрдВ рдЖрддрд╛ рд╣реИред рд╡рд┐рдЪрд╛рд░ рд╕рдореВрд╣реЛрдВ рдХреА рдкреВрд░реА рд╕реВрдЪреА рдХреЛ рдХрдИ рдкреИрдХреЗрдЬреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдирд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдкреИрдХреЗрдЬ рдореЗрдВ, 50 рд╕рдмрд╕реЗ рд╕рдорд╛рди рдЯреИрдЧ рд╕рдореВрд╣ рдвреВрдВрдвреЗрдВ, рдФрд░ рдлрд┐рд░ рдЙрдирдореЗрдВ рд╕реЗ рдЕрдВрддрд┐рдо 50 рд╕рдмрд╕реЗ рд╕рдорд╛рди рдорд┐рд▓рддреЗ рд╣реИрдВред
GetFiftyMostSimilarGroups
рдХрд╛ рдмрд╣реБ-рд╕рдВрд╕реНрдХрд░рдг рд╕рдВрд╕реНрдХрд░рдг рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
GetFiftyMostSimilarGroupsMultiThread public TagsGroup[] GetFiftyMostSimilarGroupsMultiThread(TagsGroup value) { const int resultLength = 50;
GetFiftyMostSimilarGroupsMultiThreadCore
GetFiftyMostSimilarGroups
:
GetFiftyMostSimilarGroupsMultiThreadCore List<TagsSimilarityInfo> GetFiftyMostSimilarGroupsMultiThreadCore(TagsGroup value, int leftIndex, int rightIndex) { const int resultLength = 50; List<TagsSimilarityInfo> list = new List<TagsSimilarityInfo>(resultLength); for (int groupIndex = leftIndex; groupIndex < rightIndex; groupIndex++) { TagsGroup tagsGroup = Groups[groupIndex]; int similarityValue = TagsGroup.MeasureSimilarity(value, tagsGroup); TagsSimilarityInfo newInfo = new TagsSimilarityInfo(groupIndex, similarityValue); if (list.Count == resultLength && list[resultLength - 1].CompareTo(newInfo) == -1) { continue; } int index = ~list.BinarySearch(newInfo); list.Insert(index, newInfo); if (list.Count > resultLength) { list.RemoveAt(resultLength); } } return list; }
MergeTaskResults
. - taskResults . , , . , threadsCount
, : , , , :
MergeTaskResults TagsGroup[] MergeTaskResults(int resultLength, int threadsCount, List<TagsSimilarityInfo>[] taskResults) { TagsGroup[] result = new TagsGroup[resultLength]; int[] indices = new int[threadsCount]; for (int i = 0; i < resultLength; i++) { int minIndex = 0; TagsSimilarityInfo currentBest = taskResults[minIndex][indices[minIndex]]; for (int j = 0; j < threadsCount; j++) { var current = taskResults[j][indices[j]]; if (current.CompareTo(currentBest) == -1) { minIndex = j; currentBest = taskResults[minIndex][indices[minIndex]]; } } int groupIndex = currentBest.Index; result[i] = Groups[groupIndex]; indices[minIndex]++; } return result; }
indices
taskResults
;minIndex
тАФ taskResults
, ;currentBest
тАФ - ;current
тАФ - ;
:
. . , , 4 50. , , .