ആമുഖം
മോസ്കോയിൽ നടന്ന ഗോഫർകോൺ റഷ്യ 2019 കോൺഫറൻസിൽ ഇംഗ്ലീഷിലും നിസ്നി നോവ്ഗൊറോഡിൽ നടന്ന മീറ്റിംഗിൽ റഷ്യൻ ഭാഷയിലും ഞാൻ ഈ റിപ്പോർട്ട് നൽകി. ഞങ്ങൾ ഒരു ബിറ്റ്മാപ്പ് സൂചികയെക്കുറിച്ചാണ് സംസാരിക്കുന്നത് - ബി-ട്രീയേക്കാൾ സാധാരണമല്ല, പക്ഷേ രസകരമല്ല. പങ്കിടുന്നു
ഒരു ബിറ്റ്മാപ്പ് സൂചിക എങ്ങനെ പ്രവർത്തിക്കുന്നു, എപ്പോൾ മികച്ചതായിരിക്കുമ്പോൾ, മറ്റ് സൂചികകളേക്കാൾ മോശമാകുമ്പോൾ, ഏതൊക്കെ സന്ദർഭങ്ങളിൽ അത് അവയേക്കാൾ വളരെ വേഗതയുള്ളതാണെന്ന് ഞങ്ങൾ നോക്കും; ഏതൊക്കെ ജനപ്രിയ ഡിബിഎംഎസുകൾക്ക് ഇതിനകം ബിറ്റ്മാപ്പ് സൂചികകൾ ഉണ്ടെന്ന് നോക്കാം; ഗോയിൽ നമ്മുടേത് എഴുതാൻ ശ്രമിക്കാം. "ഡെസേർട്ടിനായി" ഞങ്ങളുടെ സ്വന്തം സൂപ്പർ ഫാസ്റ്റ് പ്രത്യേക ഡാറ്റാബേസ് സൃഷ്ടിക്കാൻ ഞങ്ങൾ റെഡിമെയ്ഡ് ലൈബ്രറികൾ ഉപയോഗിക്കും.
എന്റെ സൃഷ്ടികൾ നിങ്ങൾക്ക് ഉപയോഗപ്രദവും രസകരവുമാകുമെന്ന് ഞാൻ ശരിക്കും പ്രതീക്ഷിക്കുന്നു. പോകൂ!
ആമുഖം
എല്ലാവർക്കും ഹായ്! വൈകുന്നേരം ആറുമണി, ഞങ്ങൾ എല്ലാവരും വളരെ ക്ഷീണിതരാണ്. വിരസമായ ഡാറ്റാബേസ് സൂചിക സിദ്ധാന്തത്തെക്കുറിച്ച് സംസാരിക്കാനുള്ള മികച്ച സമയം, അല്ലേ? വിഷമിക്കേണ്ട, സോഴ്സ് കോഡിന്റെ രണ്ട് വരികൾ എനിക്കവിടെയുണ്ട്. 🙂
എല്ലാ തമാശകളും മാറ്റിനിർത്തിയാൽ, റിപ്പോർട്ടിൽ വിവരങ്ങൾ നിറഞ്ഞതാണ്, ഞങ്ങൾക്ക് കൂടുതൽ സമയമില്ല. അതുകൊണ്ട് നമുക്ക് തുടങ്ങാം.
ഇന്ന് ഞാൻ ഇനിപ്പറയുന്നവയെക്കുറിച്ച് സംസാരിക്കും:
- സൂചികകൾ എന്തൊക്കെയാണ്;
- എന്താണ് ബിറ്റ്മാപ്പ് സൂചിക;
- എവിടെയാണ് ഇത് ഉപയോഗിക്കുന്നത്, എവിടെയാണ് ഉപയോഗിക്കാത്തത്, എന്തുകൊണ്ട്;
- Go-യിൽ ലളിതമായ നടപ്പാക്കലും കംപൈലറുമായുള്ള ഒരു ചെറിയ പോരാട്ടവും;
- ഗോ അസംബ്ലറിൽ കുറച്ച് ലളിതവും എന്നാൽ കൂടുതൽ ഉൽപ്പാദനക്ഷമതയുള്ളതുമായ നടപ്പാക്കൽ;
- ബിറ്റ്മാപ്പ് സൂചികകളുടെ "പ്രശ്നങ്ങൾ";
- നിലവിലുള്ള നടപ്പാക്കലുകൾ.
അപ്പോൾ എന്താണ് സൂചികകൾ?
പ്രധാന ഡാറ്റയ്ക്ക് പുറമേ ഞങ്ങൾ പരിപാലിക്കുകയും അപ്ഡേറ്റ് ചെയ്യുകയും ചെയ്യുന്ന ഒരു പ്രത്യേക ഡാറ്റാ ഘടനയാണ് സൂചിക. തിരയൽ വേഗത്തിലാക്കാൻ ഇത് ഉപയോഗിക്കുന്നു. സൂചികകളില്ലാതെ, തിരയലിന് ഡാറ്റ പൂർണ്ണമായി പരിശോധിക്കേണ്ടതുണ്ട് (പൂർണ്ണ സ്കാൻ എന്ന് വിളിക്കുന്ന ഒരു പ്രക്രിയ), ഈ പ്രക്രിയയ്ക്ക് ലീനിയർ അൽഗോരിതം സങ്കീർണ്ണതയുണ്ട്. എന്നാൽ ഡാറ്റാബേസുകളിൽ സാധാരണയായി വലിയ അളവിലുള്ള ഡാറ്റ അടങ്ങിയിരിക്കുന്നു, രേഖീയ സങ്കീർണ്ണത വളരെ മന്ദഗതിയിലാണ്. എബൌട്ട്, നമുക്ക് ഒരു ലോഗരിഥമിക് അല്ലെങ്കിൽ സ്ഥിരമായ ഒന്ന് ലഭിക്കും.
ഇത് വളരെ സങ്കീർണ്ണമായ വിഷയമാണ്, സൂക്ഷ്മതകളും ട്രേഡ്-ഓഫുകളും നിറഞ്ഞതാണ്, എന്നാൽ ദശാബ്ദങ്ങളുടെ ഡാറ്റാബേസ് വികസനവും ഗവേഷണവും പരിശോധിച്ച ശേഷം, ഡാറ്റാബേസ് സൂചികകൾ സൃഷ്ടിക്കുന്നതിന് വ്യാപകമായി ഉപയോഗിക്കുന്ന കുറച്ച് സമീപനങ്ങളേ ഉള്ളൂ എന്ന് പറയാൻ ഞാൻ തയ്യാറാണ്.
ആദ്യ സമീപനം, ശ്രേണീകൃതമായി തിരച്ചിൽ ഇടം കുറയ്ക്കുകയും, തിരയൽ സ്ഥലത്തെ ചെറിയ ഭാഗങ്ങളായി വിഭജിക്കുകയും ചെയ്യുക എന്നതാണ്.
പലതരം മരങ്ങൾ ഉപയോഗിച്ചാണ് നമ്മൾ സാധാരണയായി ഇത് ചെയ്യുന്നത്. വ്യത്യസ്ത വിഷയങ്ങളായി വിഭജിച്ചിരിക്കുന്ന മെറ്റീരിയലുകളുടെ ചെറിയ പെട്ടികൾ അടങ്ങുന്ന നിങ്ങളുടെ ക്ലോസറ്റിലെ മെറ്റീരിയലുകളുടെ ഒരു വലിയ ബോക്സ് ഒരു ഉദാഹരണമാണ്. നിങ്ങൾക്ക് മെറ്റീരിയലുകൾ ആവശ്യമുണ്ടെങ്കിൽ, "കുക്കികൾ" എന്ന് പറയുന്നതിനേക്കാൾ "മെറ്റീരിയലുകൾ" എന്ന് പറയുന്ന ഒരു ബോക്സിൽ നിങ്ങൾ അവ തിരയും, അല്ലേ?
ആവശ്യമുള്ള ഘടകമോ ഘടകങ്ങളുടെ ഗ്രൂപ്പോ ഉടനടി തിരഞ്ഞെടുക്കുക എന്നതാണ് രണ്ടാമത്തെ സമീപനം. ഞങ്ങൾ ഇത് ഹാഷ് മാപ്പുകളിലോ റിവേഴ്സ് ഇൻഡക്സുകളിലോ ചെയ്യുന്നു. ഹാഷ് മാപ്പുകൾ ഉപയോഗിക്കുന്നത് മുമ്പത്തെ ഉദാഹരണവുമായി വളരെ സാമ്യമുള്ളതാണ്, എന്നാൽ ബോക്സുകളുടെ ഒരു പെട്ടിക്ക് പകരം, നിങ്ങളുടെ ക്ലോസറ്റിൽ അവസാന ഇനങ്ങളുടെ ഒരു കൂട്ടം ചെറിയ ബോക്സുകൾ ഉണ്ട്.
മൂന്നാമത്തെ സമീപനം തിരയലിന്റെ ആവശ്യകത ഇല്ലാതാക്കുക എന്നതാണ്. ബ്ലൂം ഫിൽട്ടറുകൾ അല്ലെങ്കിൽ കുക്കൂ ഫിൽട്ടറുകൾ ഉപയോഗിച്ചാണ് ഞങ്ങൾ ഇത് ചെയ്യുന്നത്. ആദ്യത്തേത് തൽക്ഷണം ഉത്തരം നൽകുന്നു, തിരയുന്നതിൽ നിന്ന് നിങ്ങളെ രക്ഷിക്കുന്നു.
ആധുനിക ഹാർഡ്വെയർ നമുക്ക് നൽകുന്ന എല്ലാ ശക്തിയും പൂർണ്ണമായി ഉപയോഗിക്കുക എന്നതാണ് അവസാന സമീപനം. ബിറ്റ്മാപ്പ് സൂചികകളിൽ നമ്മൾ ചെയ്യുന്നത് ഇതാണ്. അതെ, അവ ഉപയോഗിക്കുമ്പോൾ നമുക്ക് ചിലപ്പോൾ മുഴുവൻ സൂചികയിലൂടെയും പോകേണ്ടതുണ്ട്, പക്ഷേ ഞങ്ങൾ അത് വളരെ കാര്യക്ഷമമായി ചെയ്യുന്നു.
ഞാൻ പറഞ്ഞതുപോലെ, ഡാറ്റാബേസ് സൂചികകളുടെ വിഷയം വിശാലവും വിട്ടുവീഴ്ചകൾ നിറഞ്ഞതുമാണ്. ഇതിനർത്ഥം ചിലപ്പോൾ നമുക്ക് ഒരേ സമയം നിരവധി സമീപനങ്ങൾ ഉപയോഗിക്കാമെന്നാണ്: തിരയൽ കൂടുതൽ വേഗത്തിലാക്കണമെങ്കിൽ, അല്ലെങ്കിൽ സാധ്യമായ എല്ലാ തിരയൽ തരങ്ങളും ഉൾപ്പെടുത്തണമെങ്കിൽ.
ബിറ്റ്മാപ്പ് സൂചികകൾ - ഇന്ന് ഞാൻ ഇവയുടെ ഏറ്റവും അറിയപ്പെടുന്ന സമീപനത്തെക്കുറിച്ച് സംസാരിക്കും.
ഈ വിഷയത്തിൽ സംസാരിക്കാൻ ഞാൻ ആരാണ്?
ഞാൻ ബഡൂവിൽ ഒരു ടീം ലീഡായി പ്രവർത്തിക്കുന്നു (ഒരുപക്ഷേ ഞങ്ങളുടെ മറ്റ് ഉൽപ്പന്നമായ ബംബിളുമായി നിങ്ങൾക്ക് കൂടുതൽ പരിചിതമായിരിക്കും). ലോകമെമ്പാടുമുള്ള 400 ദശലക്ഷത്തിലധികം ഉപയോക്താക്കളും അവർക്ക് ഏറ്റവും അനുയോജ്യമായത് തിരഞ്ഞെടുക്കുന്ന നിരവധി സവിശേഷതകളും ഞങ്ങൾക്ക് ഇതിനകം തന്നെയുണ്ട്. ബിറ്റ്മാപ്പ് സൂചികകൾ ഉൾപ്പെടെയുള്ള ഇഷ്ടാനുസൃത സേവനങ്ങൾ ഉപയോഗിച്ചാണ് ഞങ്ങൾ ഇത് ചെയ്യുന്നത്.
അപ്പോൾ എന്താണ് ബിറ്റ്മാപ്പ് സൂചിക?
ബിറ്റ്മാപ്പ് സൂചികകൾ, പേര് സൂചിപ്പിക്കുന്നത് പോലെ, ഒരു തിരയൽ സൂചിക നടപ്പിലാക്കാൻ ബിറ്റ്മാപ്പുകൾ അല്ലെങ്കിൽ ബിറ്റ്സെറ്റുകൾ ഉപയോഗിക്കുക. ഒരു പക്ഷിയുടെ കാഴ്ചയിൽ നിന്ന്, ഈ സൂചികയിൽ ഏതെങ്കിലും എന്റിറ്റികളെ (ആളുകൾ പോലുള്ളവ) പ്രതിനിധീകരിക്കുന്ന ഒന്നോ അതിലധികമോ ബിറ്റ്മാപ്പുകളും അവയുടെ പ്രോപ്പർട്ടികൾ അല്ലെങ്കിൽ പാരാമീറ്ററുകളും (പ്രായം, കണ്ണ് നിറം മുതലായവ) ബിറ്റ് ഓപ്പറേഷനുകൾ ഉപയോഗിക്കുന്ന ഒരു അൽഗോരിതം (AND, OR, NOT) അടങ്ങിയിരിക്കുന്നു. ) തിരയൽ ചോദ്യത്തിന് ഉത്തരം നൽകാൻ.
നിരവധി താഴ്ന്ന കാർഡിനാലിറ്റി കോളങ്ങളിൽ ("കണ്ണിന്റെ നിറം" അല്ലെങ്കിൽ "വൈവാഹിക നില" എന്നതിന് എതിരായി "നഗര കേന്ദ്രത്തിൽ നിന്നുള്ള ദൂരം" പോലെയുള്ള എന്തെങ്കിലും ചിന്തിക്കുക) തിരയലുകൾ സംയോജിപ്പിച്ച് തിരയുന്ന സന്ദർഭങ്ങളിൽ ബിറ്റ്മാപ്പ് സൂചികകൾ ഏറ്റവും അനുയോജ്യവും വളരെ കാര്യക്ഷമവുമാണെന്ന് ഞങ്ങളോട് പറയപ്പെടുന്നു. എന്നാൽ ഉയർന്ന കാർഡിനാലിറ്റി നിരകൾക്കും അവ നന്നായി പ്രവർത്തിക്കുന്നുവെന്ന് ഞാൻ പിന്നീട് കാണിക്കും.
ബിറ്റ്മാപ്പ് സൂചികയുടെ ഏറ്റവും ലളിതമായ ഉദാഹരണം നോക്കാം.
ഇതുപോലുള്ള ബൈനറി ഗുണങ്ങളുള്ള മോസ്കോ റെസ്റ്റോറന്റുകളുടെ ഒരു ലിസ്റ്റ് ഞങ്ങളുടെ പക്കലുണ്ടെന്ന് സങ്കൽപ്പിക്കുക:
- മെട്രോയ്ക്ക് സമീപം;
- സ്വകാര്യ പാർക്കിംഗ് ഉണ്ട്;
- ഒരു വരാന്തയുണ്ട് (ടെറസുണ്ട്);
- നിങ്ങൾക്ക് ഒരു ടേബിൾ റിസർവ് ചെയ്യാം (റിസർവേഷനുകൾ സ്വീകരിക്കുന്നു);
- സസ്യാഹാരികൾക്ക് അനുയോജ്യം (വെഗൻ ഫ്രണ്ട്ലി);
- ചെലവേറിയ (ചെലവേറിയത്).
നമുക്ക് ഓരോ റെസ്റ്റോറന്റിനും 0 മുതൽ ആരംഭിക്കുന്ന ഒരു സീക്വൻസ് നമ്പർ നൽകുകയും 6 ബിറ്റ്മാപ്പുകൾക്കായി മെമ്മറി അനുവദിക്കുകയും ചെയ്യാം (ഓരോ സ്വഭാവത്തിനും ഒന്ന്). റസ്റ്റോറന്റിന് ഈ പ്രോപ്പർട്ടി ഉണ്ടോ ഇല്ലയോ എന്നതിനെ ആശ്രയിച്ച് ഞങ്ങൾ ഈ ബിറ്റ്മാപ്പുകൾ ജനകീയമാക്കും. റെസ്റ്റോറന്റ് 4 ന് ഒരു വരാന്തയുണ്ടെങ്കിൽ, "വരാന്തയുണ്ട്" എന്ന ബിറ്റ്മാപ്പിലെ ബിറ്റ് നമ്പർ 4 1 ആയി സജ്ജീകരിക്കും (വരാന്ത ഇല്ലെങ്കിൽ, 0 ആയി).
ഇപ്പോൾ നമുക്ക് സാധ്യമായ ഏറ്റവും ലളിതമായ ബിറ്റ്മാപ്പ് സൂചികയുണ്ട്, ഇതുപോലുള്ള ചോദ്യങ്ങൾക്ക് ഉത്തരം നൽകാൻ ഞങ്ങൾക്ക് ഇത് ഉപയോഗിക്കാം:
- "വെജിറ്റേറിയൻ-സൗഹൃദ ഭക്ഷണശാലകൾ എന്നെ കാണിക്കൂ";
- "നിങ്ങൾക്ക് ഒരു മേശ റിസർവ് ചെയ്യാൻ കഴിയുന്ന ഒരു വരാന്തയുള്ള വിലകുറഞ്ഞ റെസ്റ്റോറന്റുകൾ എന്നെ കാണിക്കൂ."
എങ്ങനെ? നമുക്ക് ഒന്ന് നോക്കാം. ആദ്യത്തെ അഭ്യർത്ഥന വളരെ ലളിതമാണ്. നമ്മൾ ചെയ്യേണ്ടത് "വെജിറ്റേറിയൻ ഫ്രണ്ട്ലി" ബിറ്റ്മാപ്പ് എടുത്ത് അതിനെ ബിറ്റുകൾ തുറന്നുകാട്ടുന്ന റെസ്റ്റോറന്റുകളുടെ ഒരു ലിസ്റ്റാക്കി മാറ്റുക എന്നതാണ്.
രണ്ടാമത്തെ അഭ്യർത്ഥന കുറച്ചുകൂടി സങ്കീർണ്ണമാണ്. വിലകുറഞ്ഞ റെസ്റ്റോറന്റുകളുടെ ഒരു ലിസ്റ്റ് ലഭിക്കാൻ "വിലയേറിയ" ബിറ്റ്മാപ്പിലെ NOT ബിറ്റ്മാപ്പ് ഉപയോഗിക്കേണ്ടതുണ്ട്, തുടർന്ന് അത് "എനിക്ക് ഒരു ടേബിൾ ബുക്ക് ചെയ്യാമോ" ബിറ്റ്മാപ്പിനൊപ്പം "ഒരു വരാന്തയുണ്ട്" ബിറ്റ്മാപ്പിനൊപ്പം ഫലം. തത്ഫലമായുണ്ടാകുന്ന ബിറ്റ്മാപ്പിൽ ഞങ്ങളുടെ എല്ലാ മാനദണ്ഡങ്ങളും പാലിക്കുന്ന സ്ഥാപനങ്ങളുടെ ഒരു ലിസ്റ്റ് അടങ്ങിയിരിക്കും. ഈ ഉദാഹരണത്തിൽ, ഇത് യുനോസ്റ്റ് റെസ്റ്റോറന്റ് മാത്രമാണ്.
ധാരാളം സിദ്ധാന്തങ്ങൾ ഉൾപ്പെട്ടിട്ടുണ്ട്, പക്ഷേ വിഷമിക്കേണ്ട, ഞങ്ങൾ കോഡ് ഉടൻ കാണും.
ബിറ്റ്മാപ്പ് സൂചികകൾ എവിടെയാണ് ഉപയോഗിക്കുന്നത്?
നിങ്ങൾ ബിറ്റ്മാപ്പ് സൂചികകൾ ഗൂഗിൾ ചെയ്യുകയാണെങ്കിൽ, 90% ഉത്തരങ്ങളും ഒറാക്കിൾ ഡിബിയുമായി ബന്ധപ്പെട്ടതായിരിക്കും. എന്നാൽ മറ്റ് ഡിബിഎംഎസുകളും അത്തരമൊരു രസകരമായ കാര്യത്തെ പിന്തുണയ്ക്കുന്നു, അല്ലേ? ശരിക്കുമല്ല.
പ്രധാന പ്രതികളുടെ പട്ടികയിലേക്ക് പോകാം.
MySQL ഇതുവരെ ബിറ്റ്മാപ്പ് സൂചികകളെ പിന്തുണയ്ക്കുന്നില്ല, എന്നാൽ ഈ ഓപ്ഷൻ ചേർക്കാൻ നിർദ്ദേശിക്കുന്ന ഒരു നിർദ്ദേശമുണ്ട് (
PostgreSQL ബിറ്റ്മാപ്പ് സൂചികകളെ പിന്തുണയ്ക്കുന്നില്ല, എന്നാൽ മറ്റ് ഒന്നിലധികം സൂചികകളിലുടനീളം തിരയൽ ഫലങ്ങൾ സംയോജിപ്പിക്കുന്നതിന് ലളിതമായ ബിറ്റ്മാപ്പുകളും ബിറ്റ് പ്രവർത്തനങ്ങളും ഉപയോഗിക്കുന്നു.
Tarantool ബിറ്റ്സെറ്റ് സൂചികകൾ ഉണ്ട് കൂടാതെ അവയിൽ ലളിതമായ തിരയലുകൾ പിന്തുണയ്ക്കുന്നു.
റെഡിസിന് ലളിതമായ ബിറ്റ്ഫീൽഡുകൾ ഉണ്ട്
MongoDB ഇതുവരെ ബിറ്റ്മാപ്പ് സൂചികകളെ പിന്തുണയ്ക്കുന്നില്ല, എന്നാൽ ഈ ഓപ്ഷൻ ചേർക്കാൻ നിർദ്ദേശിക്കുന്ന ഒരു നിർദ്ദേശവുമുണ്ട്.
ഇലാസ്റ്റിക് സെർച്ച് ആന്തരികമായി ബിറ്റ്മാപ്പുകൾ ഉപയോഗിക്കുന്നു
- എന്നാൽ ഞങ്ങളുടെ വീട്ടിൽ ഒരു പുതിയ അയൽക്കാരൻ പ്രത്യക്ഷപ്പെട്ടു: പിലോസ. Go-ൽ എഴുതപ്പെട്ട ഒരു പുതിയ നോൺ-റിലേഷണൽ ഡാറ്റാബേസാണിത്. ഇതിൽ ബിറ്റ്മാപ്പ് സൂചികകൾ മാത്രമേ അടങ്ങിയിട്ടുള്ളൂ, അവയിൽ എല്ലാം അടിസ്ഥാനമാക്കിയുള്ളതാണ്. ഞങ്ങൾ അതിനെക്കുറിച്ച് കുറച്ച് കഴിഞ്ഞ് സംസാരിക്കും.
ഗോയിൽ നടപ്പിലാക്കൽ
എന്നാൽ എന്തുകൊണ്ടാണ് ബിറ്റ്മാപ്പ് സൂചികകൾ വളരെ അപൂർവ്വമായി ഉപയോഗിക്കുന്നത്? ഈ ചോദ്യത്തിന് ഉത്തരം നൽകുന്നതിനുമുമ്പ്, Go- ൽ വളരെ ലളിതമായ ഒരു ബിറ്റ്മാപ്പ് സൂചിക എങ്ങനെ നടപ്പിലാക്കാമെന്ന് ഞാൻ നിങ്ങളെ കാണിക്കാൻ ആഗ്രഹിക്കുന്നു.
ബിറ്റ്മാപ്പുകൾ അടിസ്ഥാനപരമായി ഡാറ്റയുടെ കഷണങ്ങൾ മാത്രമാണ്. ഗോയിൽ, ഇതിനായി നമുക്ക് ബൈറ്റ് സ്ലൈസുകൾ ഉപയോഗിക്കാം.
ഒരു റെസ്റ്റോറന്റ് സ്വഭാവത്തിന് ഞങ്ങൾക്ക് ഒരു ബിറ്റ്മാപ്പ് ഉണ്ട്, ബിറ്റ്മാപ്പിലെ ഓരോ ബിറ്റും ഒരു പ്രത്യേക റെസ്റ്റോറന്റിന് ഈ പ്രോപ്പർട്ടി ഉണ്ടോ ഇല്ലയോ എന്ന് സൂചിപ്പിക്കുന്നു.
ഞങ്ങൾക്ക് രണ്ട് സഹായ പ്രവർത്തനങ്ങൾ ആവശ്യമാണ്. റാൻഡം ഡാറ്റ ഉപയോഗിച്ച് ഞങ്ങളുടെ ബിറ്റ്മാപ്പുകൾ പൂരിപ്പിക്കാൻ ഒരെണ്ണം ഉപയോഗിക്കും. ക്രമരഹിതമായത്, എന്നാൽ റസ്റ്റോറന്റിന് ഓരോ പ്രോപ്പർട്ടിയും ഉണ്ടെന്ന് ഒരു നിശ്ചിത സംഭാവ്യതയോടെ. ഉദാഹരണത്തിന്, നിങ്ങൾക്ക് ഒരു മേശ റിസർവ് ചെയ്യാൻ കഴിയാത്ത വളരെ കുറച്ച് റെസ്റ്റോറന്റുകൾ മോസ്കോയിൽ ഉണ്ടെന്ന് ഞാൻ വിശ്വസിക്കുന്നു, കൂടാതെ ഏകദേശം 20% സ്ഥാപനങ്ങളും സസ്യാഹാരികൾക്ക് അനുയോജ്യമാണെന്ന് എനിക്ക് തോന്നുന്നു.
രണ്ടാമത്തെ പ്രവർത്തനം ബിറ്റ്മാപ്പിനെ റെസ്റ്റോറന്റുകളുടെ ഒരു ലിസ്റ്റാക്കി മാറ്റും.
“ഒരു നടുമുറ്റം ഉള്ളതും റിസർവേഷൻ ചെയ്യാൻ കഴിയുന്നതുമായ വിലകുറഞ്ഞ റെസ്റ്റോറന്റുകൾ എന്നെ കാണിക്കൂ” എന്ന ചോദ്യത്തിന് ഉത്തരം നൽകാൻ ഞങ്ങൾക്ക് രണ്ട് ബിറ്റ് പ്രവർത്തനങ്ങൾ ആവശ്യമാണ്: NOT, AND.
കൂടുതൽ സങ്കീർണ്ണവും അല്ലാത്തതുമായ ഓപ്പറേറ്റർ ഉപയോഗിച്ച് നമുക്ക് ഞങ്ങളുടെ കോഡ് അൽപ്പം ലളിതമാക്കാം.
ഈ ഓരോ പ്രവർത്തനത്തിനും ഞങ്ങൾക്ക് പ്രവർത്തനങ്ങൾ ഉണ്ട്. അവ രണ്ടും സ്ലൈസുകളിലൂടെ കടന്നുപോയി, ഓരോന്നിൽ നിന്നും അനുബന്ധ ഘടകങ്ങൾ എടുത്ത്, അവയെ ഒരു ബിറ്റ് ഓപ്പറേഷനുമായി സംയോജിപ്പിച്ച് ഫലമായുണ്ടാകുന്ന സ്ലൈസിലേക്ക് ഫലം ഇടുക.
തിരയൽ ചോദ്യത്തിന് ഉത്തരം നൽകാൻ ഇപ്പോൾ നമുക്ക് ബിറ്റ്മാപ്പുകളും ഫംഗ്ഷനുകളും ഉപയോഗിക്കാം.
ഫംഗ്ഷനുകൾ വളരെ ലളിതമാണെങ്കിലും, ഓരോ തവണയും ഫംഗ്ഷൻ വിളിക്കുമ്പോൾ ഫലമായുണ്ടാകുന്ന പുതിയ സ്ലൈസ് തിരികെ നൽകാതെ ഞങ്ങൾ ധാരാളം പണം ലാഭിച്ചുവെങ്കിലും പ്രകടനം അത്ര ഉയർന്നതല്ല.
pprof ഉപയോഗിച്ച് കുറച്ച് പ്രൊഫൈലിംഗ് നടത്തിയതിന് ശേഷം, Go കംപൈലറിന് വളരെ ലളിതവും എന്നാൽ വളരെ പ്രധാനപ്പെട്ടതുമായ ഒപ്റ്റിമൈസേഷൻ നഷ്ടമായതായി ഞാൻ ശ്രദ്ധിച്ചു: ഫംഗ്ഷൻ ഇൻലൈനിംഗ്.
ഗോ കംപൈലർ സ്ലൈസുകളിലൂടെ കടന്നുപോകുന്ന ലൂപ്പുകളെ ഭയങ്കരമായി ഭയപ്പെടുന്നു, അത്തരം ലൂപ്പുകൾ ഉൾക്കൊള്ളുന്ന ഇൻലൈൻ ഫംഗ്ഷനുകൾ വ്യക്തമായി നിരസിക്കുന്നു എന്നതാണ് വസ്തുത.
പക്ഷെ എനിക്ക് ഭയമില്ല, പഴയ നല്ല കാലത്തെ പോലെ ഒരു ലൂപ്പിന് പകരം ഗോട്ടോ ഉപയോഗിച്ച് എനിക്ക് കമ്പൈലറിനെ കബളിപ്പിക്കാൻ കഴിയും.
കൂടാതെ, നിങ്ങൾക്ക് കാണാനാകുന്നതുപോലെ, ഇപ്പോൾ കമ്പൈലർ ഞങ്ങളുടെ പ്രവർത്തനത്തെ സന്തോഷത്തോടെ ഇൻലൈൻ ചെയ്യും! തൽഫലമായി, ഏകദേശം 2 മൈക്രോസെക്കൻഡ് ലാഭിക്കാൻ ഞങ്ങൾക്ക് കഴിയുന്നു. മോശമല്ല!
നിങ്ങൾ അസംബ്ലി ഔട്ട്പുട്ട് സൂക്ഷ്മമായി നോക്കിയാൽ രണ്ടാമത്തെ തടസ്സം കാണാൻ എളുപ്പമാണ്. കംപൈലർ ഞങ്ങളുടെ ഹോട്ടസ്റ്റ് ലൂപ്പിനുള്ളിൽ തന്നെ ഒരു സ്ലൈസ് ബൗണ്ടറി ചെക്ക് ചേർത്തു. ഗോ ഒരു സുരക്ഷിത ഭാഷയാണെന്നതാണ് വസ്തുത, എന്റെ മൂന്ന് വാദങ്ങൾ (മൂന്ന് സ്ലൈസുകൾ) വ്യത്യസ്ത വലുപ്പത്തിലുള്ളതാണെന്ന് കംപൈലർ ഭയപ്പെടുന്നു. എല്ലാത്തിനുമുപരി, ബഫർ ഓവർഫ്ലോ എന്ന് വിളിക്കപ്പെടുന്നതിന്റെ സൈദ്ധാന്തിക സാധ്യതയുണ്ടാകും.
എല്ലാ സ്ലൈസുകളും ഒരേ വലുപ്പമാണെന്ന് കാണിച്ച് കംപൈലറിന് ഉറപ്പ് നൽകാം. ഞങ്ങളുടെ പ്രവർത്തനത്തിന്റെ തുടക്കത്തിൽ ഒരു ലളിതമായ ചെക്ക് ചേർത്തുകൊണ്ട് നമുക്ക് ഇത് ചെയ്യാൻ കഴിയും.
ഇത് കണ്ട്, കംപൈലർ സന്തോഷത്തോടെ ചെക്ക് ഒഴിവാക്കുന്നു, ഞങ്ങൾ 500 നാനോ സെക്കൻഡ് ലാഭിക്കുന്നു.
വലിയ കശാപ്പ്
ശരി, ഞങ്ങളുടെ ലളിതമായ നടപ്പാക്കലിൽ നിന്ന് കുറച്ച് പ്രകടനം പുറത്തെടുക്കാൻ ഞങ്ങൾക്ക് കഴിഞ്ഞു, എന്നാൽ ഈ ഫലം യഥാർത്ഥത്തിൽ നിലവിലെ ഹാർഡ്വെയറിൽ സാധ്യമായതിനേക്കാൾ വളരെ മോശമാണ്.
ഞങ്ങൾ ചെയ്യുന്നത് അടിസ്ഥാന ബിറ്റ് ഓപ്പറേഷനുകളാണ്, ഞങ്ങളുടെ പ്രോസസ്സറുകൾ അവ വളരെ കാര്യക്ഷമമായി നിർവഹിക്കുന്നു. പക്ഷേ, നിർഭാഗ്യവശാൽ, ഞങ്ങളുടെ പ്രോസസറിനെ വളരെ ചെറിയ ജോലികൾ ഉപയോഗിച്ച് ഞങ്ങൾ "ഫീഡ്" ചെയ്യുന്നു. ഞങ്ങളുടെ പ്രവർത്തനങ്ങൾ ബൈറ്റ്-ബൈ-ബൈറ്റ് അടിസ്ഥാനത്തിൽ പ്രവർത്തനങ്ങൾ നടത്തുന്നു. UInt8 സ്ലൈസുകൾ ഉപയോഗിച്ച് 64-ബൈറ്റ് ചങ്കുകൾ ഉപയോഗിച്ച് പ്രവർത്തിക്കാൻ ഞങ്ങളുടെ കോഡ് വളരെ എളുപ്പത്തിൽ മാറ്റാനാകും.
നിങ്ങൾക്ക് കാണാനാകുന്നതുപോലെ, ഈ ചെറിയ മാറ്റം ബാച്ച് വലുപ്പം എട്ട് മടങ്ങ് വർദ്ധിപ്പിച്ചുകൊണ്ട് ഞങ്ങളുടെ പ്രോഗ്രാമിനെ എട്ട് മടങ്ങ് വേഗത്തിലാക്കി. നേട്ടം രേഖീയമാണെന്ന് പറയാം.
അസംബ്ലറിൽ നടപ്പിലാക്കൽ
എന്നാൽ ഇത് അവസാനമല്ല. ഞങ്ങളുടെ പ്രോസസറുകൾക്ക് 16, 32, 64 ബൈറ്റുകൾ എന്നിവയുടെ ഭാഗങ്ങളിൽ പ്രവർത്തിക്കാൻ കഴിയും. അത്തരം "വിശാലമായ" പ്രവർത്തനങ്ങളെ സിംഗിൾ ഇൻസ്ട്രക്ഷൻ മൾട്ടിപ്പിൾ ഡാറ്റ (SIMD; ഒരു നിർദ്ദേശം, നിരവധി ഡാറ്റ) എന്ന് വിളിക്കുന്നു, കൂടാതെ അത്തരം പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കുന്ന തരത്തിൽ കോഡ് രൂപാന്തരപ്പെടുത്തുന്ന പ്രക്രിയയെ വെക്ടറൈസേഷൻ എന്ന് വിളിക്കുന്നു.
നിർഭാഗ്യവശാൽ, വെക്ടറൈസേഷനിൽ Go കംപൈലർ വളരെ മികച്ചതാണ്. നിലവിൽ, ഗോ കോഡ് വെക്ടറൈസ് ചെയ്യാനുള്ള ഏക മാർഗം ഗോ അസംബ്ലർ ഉപയോഗിച്ച് ഈ പ്രവർത്തനങ്ങൾ സ്വമേധയാ എടുക്കുകയും ഇടുകയും ചെയ്യുക എന്നതാണ്.
ഗോ അസംബ്ലർ ഒരു വിചിത്ര മൃഗമാണ്. അസംബ്ലി ഭാഷ നിങ്ങൾ എഴുതുന്ന കമ്പ്യൂട്ടറിന്റെ ആർക്കിടെക്ചറുമായി വളരെയധികം ബന്ധപ്പെട്ടിരിക്കുന്ന ഒന്നാണെന്ന് നിങ്ങൾക്കറിയാം, പക്ഷേ Go-യിൽ അങ്ങനെയല്ല. ഗോ അസംബ്ലർ ഒരു IRL (ഇന്റർമീഡിയറ്റ് പ്രാതിനിധ്യ ഭാഷ) അല്ലെങ്കിൽ ഇന്റർമീഡിയറ്റ് ഭാഷ പോലെയാണ്: ഇത് പ്രായോഗികമായി പ്ലാറ്റ്ഫോം സ്വതന്ത്രമാണ്. റോബ് പൈക്ക് മികച്ച പ്രകടനമാണ് കാഴ്ചവെച്ചത്
കൂടാതെ, പൊതുവായി അംഗീകരിക്കപ്പെട്ട AT&T, Intel ഫോർമാറ്റുകളിൽ നിന്ന് വ്യത്യസ്തമായ ഒരു അസാധാരണമായ പ്ലാൻ 9 ഫോർമാറ്റ് Go ഉപയോഗിക്കുന്നു.
ഗോ അസംബ്ലർ കൈകൊണ്ട് എഴുതുന്നത് ഏറ്റവും രസകരമല്ലെന്ന് തന്നെ പറയാം.
പക്ഷേ, ഭാഗ്യവശാൽ, Go അസംബ്ലർ എഴുതാൻ ഞങ്ങളെ സഹായിക്കുന്ന രണ്ട് ഉയർന്ന തലത്തിലുള്ള ടൂളുകൾ ഇതിനകം ഉണ്ട്: PeachPy, avo. രണ്ട് യൂട്ടിലിറ്റികളും യഥാക്രമം പൈത്തണിലും ഗോയിലും എഴുതിയ ഉയർന്ന തലത്തിലുള്ള കോഡിൽ നിന്ന് ഗോ അസംബ്ലർ സൃഷ്ടിക്കുന്നു.
ഈ യൂട്ടിലിറ്റികൾ റജിസ്റ്റർ അലോക്കേഷൻ, ലൂപ്പുകൾ എഴുതൽ തുടങ്ങിയ കാര്യങ്ങൾ ലളിതമാക്കുന്നു, കൂടാതെ ഗോയിലെ അസംബ്ലി പ്രോഗ്രാമിംഗിന്റെ ലോകത്തേക്ക് പ്രവേശിക്കുന്നതിനുള്ള പ്രക്രിയയെ പൊതുവെ ലളിതമാക്കുന്നു.
ഞങ്ങൾ avo ഉപയോഗിക്കും, അതിനാൽ ഞങ്ങളുടെ പ്രോഗ്രാമുകൾ മിക്കവാറും സാധാരണ Go പ്രോഗ്രാമുകളായിരിക്കും.
ഒരു avo പ്രോഗ്രാമിന്റെ ഏറ്റവും ലളിതമായ ഉദാഹരണം ഇങ്ങനെയാണ്. നമുക്ക് ഒരു മെയിൻ() ഫംഗ്ഷൻ ഉണ്ട്, അതിൽ തന്നെ ആഡ്() ഫംഗ്ഷൻ നിർവചിക്കുന്നു, അതിന്റെ അർത്ഥം രണ്ട് അക്കങ്ങൾ ചേർക്കുക എന്നതാണ്. പേരിനനുസരിച്ച് പാരാമീറ്ററുകൾ നേടുന്നതിനും സൌജന്യവും അനുയോജ്യവുമായ പ്രോസസ്സർ രജിസ്റ്ററുകളിൽ ഒന്ന് നേടുന്നതിനും ഇവിടെ സഹായ പ്രവർത്തനങ്ങൾ ഉണ്ട്. ADDQ-ൽ കാണുന്നത് പോലെ ഓരോ പ്രോസസർ പ്രവർത്തനത്തിനും avo-യിൽ ഒരു അനുബന്ധ ഫംഗ്ഷൻ ഉണ്ട്. അവസാനമായി, ഫലമായുണ്ടാകുന്ന മൂല്യം സംഭരിക്കുന്നതിനുള്ള ഒരു സഹായ പ്രവർത്തനം ഞങ്ങൾ കാണുന്നു.
ഗോ ജനറേറ്റ് എന്ന് വിളിക്കുന്നതിലൂടെ, ഞങ്ങൾ avo-യിൽ പ്രോഗ്രാം എക്സിക്യൂട്ട് ചെയ്യും, അതിന്റെ ഫലമായി രണ്ട് ഫയലുകൾ ജനറേറ്റ് ചെയ്യപ്പെടും:
- ഗോ അസംബ്ലറിൽ തത്ഫലമായുണ്ടാകുന്ന കോഡ് ഉപയോഗിച്ച് add.s;
- രണ്ട് ലോകങ്ങളെ ബന്ധിപ്പിക്കുന്നതിന് ഫംഗ്ഷൻ ഹെഡറുകൾ ഉപയോഗിച്ച് stub.go: പോയി അസംബ്ലർ.
Avo എന്താണ് ചെയ്യുന്നതെന്നും എങ്ങനെയെന്നും ഇപ്പോൾ നമ്മൾ കണ്ടു, നമുക്ക് നമ്മുടെ പ്രവർത്തനങ്ങൾ നോക്കാം. ഫംഗ്ഷനുകളുടെ സ്കെയിലർ, വെക്റ്റർ (SIMD) പതിപ്പുകൾ ഞാൻ നടപ്പിലാക്കി.
നമുക്ക് ആദ്യം സ്കെയിലർ പതിപ്പുകൾ നോക്കാം.
മുമ്പത്തെ ഉദാഹരണത്തിലെന്നപോലെ, ഞങ്ങൾ സൗജന്യവും സാധുതയുള്ളതുമായ ഒരു പൊതു ഉദ്ദേശ്യ രജിസ്റ്ററിനായി ആവശ്യപ്പെടുന്നു, ആർഗ്യുമെന്റുകൾക്കായി ഓഫ്സെറ്റുകളും വലുപ്പങ്ങളും ഞങ്ങൾ കണക്കാക്കേണ്ടതില്ല. avo നമുക്ക് വേണ്ടിയാണ് ഇതെല്ലാം ചെയ്യുന്നത്.
പ്രകടനം മെച്ചപ്പെടുത്തുന്നതിനും Go കംപൈലറിനെ കബളിപ്പിക്കുന്നതിനും ഞങ്ങൾ ലേബലുകളും ഗോട്ടോയും (അല്ലെങ്കിൽ ജമ്പുകൾ) ഉപയോഗിച്ചിരുന്നു, എന്നാൽ ഇപ്പോൾ ഞങ്ങൾ അത് തുടക്കം മുതൽ ചെയ്യുന്നു. സൈക്കിളുകൾ ഒരു ഉയർന്ന തലത്തിലുള്ള ആശയമാണ് എന്നതാണ് കാര്യം. അസംബ്ലറിൽ, ഞങ്ങൾക്ക് ലേബലുകളും ജമ്പുകളും മാത്രമേ ഉള്ളൂ.
ശേഷിക്കുന്ന കോഡ് ഇതിനകം പരിചിതവും മനസ്സിലാക്കാവുന്നതുമായിരിക്കണം. ഞങ്ങൾ ലേബലുകളും ജമ്പുകളും ഉള്ള ഒരു ലൂപ്പ് അനുകരിക്കുന്നു, ഞങ്ങളുടെ രണ്ട് സ്ലൈസുകളിൽ നിന്ന് ഒരു ചെറിയ ഡാറ്റ എടുക്കുക, അവയെ ഒരു ബിറ്റ് ഓപ്പറേഷനുമായി സംയോജിപ്പിക്കുക (ഈ സാഹചര്യത്തിൽ അല്ല) തുടർന്ന് ഫലമായുണ്ടാകുന്ന സ്ലൈസിലേക്ക് ഫലം ഇടുക. എല്ലാം.
അവസാന അസംബ്ലർ കോഡ് ഇങ്ങനെയാണ് കാണപ്പെടുന്നത്. ഞങ്ങൾക്ക് ഓഫ്സെറ്റുകളും വലുപ്പങ്ങളും (പച്ചയിൽ ഹൈലൈറ്റ് ചെയ്തത്) കണക്കാക്കേണ്ടതില്ല അല്ലെങ്കിൽ ഉപയോഗിച്ച രജിസ്റ്ററുകളുടെ ട്രാക്ക് സൂക്ഷിക്കേണ്ടതില്ല (ചുവപ്പ് നിറത്തിൽ ഹൈലൈറ്റ് ചെയ്തിരിക്കുന്നു).
അസംബ്ലി ലാംഗ്വേജ് ഇംപ്ലിമെന്റേഷന്റെ പ്രകടനവും ഗോയിലെ മികച്ച നടപ്പാക്കലിന്റെ പ്രകടനവും താരതമ്യം ചെയ്താൽ, അത് സമാനമാണെന്ന് നമുക്ക് കാണാം. ഇത് പ്രതീക്ഷിക്കുകയും ചെയ്യുന്നു. എല്ലാത്തിനുമുപരി, ഞങ്ങൾ പ്രത്യേകിച്ച് ഒന്നും ചെയ്തില്ല - ഒരു Go കംപൈലർ എന്തുചെയ്യുമെന്ന് ഞങ്ങൾ പുനർനിർമ്മിച്ചു.
നിർഭാഗ്യവശാൽ, അസംബ്ലി ഭാഷയിൽ എഴുതിയിരിക്കുന്ന ഞങ്ങളുടെ ഫംഗ്ഷനുകൾ ഇൻലൈൻ ചെയ്യാൻ കംപൈലറിനെ നിർബന്ധിക്കാനാവില്ല. ഗോ കംപൈലറിന് നിലവിൽ അത്തരത്തിലുള്ള ഒരു ഫീച്ചർ ഇല്ല, കുറച്ച് കാലമായി ഇത് ചേർക്കാൻ അഭ്യർത്ഥനയുണ്ട്.
അസംബ്ലി ഭാഷയിലെ ചെറിയ ഫംഗ്ഷനുകളിൽ നിന്ന് ഒരു പ്രയോജനവും ലഭിക്കാൻ കഴിയാത്തത് അതുകൊണ്ടാണ്. നമുക്ക് ഒന്നുകിൽ വലിയ ഫംഗ്ഷനുകൾ എഴുതേണ്ടതുണ്ട്, അല്ലെങ്കിൽ പുതിയ മാത്ത്/ബിറ്റ്സ് പാക്കേജ് ഉപയോഗിക്കുക, അല്ലെങ്കിൽ അസംബ്ലർ ഭാഷയെ മറികടക്കുക.
ഇനി നമ്മുടെ ഫംഗ്ഷനുകളുടെ വെക്റ്റർ പതിപ്പുകൾ നോക്കാം.
ഈ ഉദാഹരണത്തിനായി, ഞാൻ AVX2 ഉപയോഗിക്കാൻ തീരുമാനിച്ചു, അതിനാൽ ഞങ്ങൾ 32-ബൈറ്റ് ചങ്കുകളിൽ പ്രവർത്തിക്കുന്ന പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കും. കോഡിന്റെ ഘടന സ്കെയിലർ പതിപ്പുമായി വളരെ സാമ്യമുള്ളതാണ്: പരാമീറ്ററുകൾ ലോഡുചെയ്യുക, ഒരു സൗജന്യ പങ്കിട്ട രജിസ്റ്ററിന് ആവശ്യപ്പെടുക തുടങ്ങിയവ.
വിശാലമായ വെക്റ്റർ പ്രവർത്തനങ്ങൾ പ്രത്യേക വൈഡ് രജിസ്റ്ററുകൾ ഉപയോഗിക്കുന്നു എന്നതാണ് ഒരു പുതുമ. 32-ബൈറ്റ് ചങ്കുകളുടെ കാര്യത്തിൽ, ഇവ Y ഉപയോഗിച്ച് പ്രിഫിക്സ് ചെയ്ത രജിസ്റ്ററുകളാണ്. അതിനാലാണ് നിങ്ങൾ കോഡിൽ YMM() ഫംഗ്ഷൻ കാണുന്നത്. ഞാൻ 512-ബിറ്റ് ചങ്കുകൾ ഉപയോഗിച്ചാണ് AVX-64 ഉപയോഗിക്കുന്നതെങ്കിൽ, പ്രിഫിക്സ് Z ആയിരിക്കും.
രണ്ടാമത്തെ പുതുമ, ലൂപ്പ് അൺറോളിംഗ് എന്ന ഒപ്റ്റിമൈസേഷൻ ഉപയോഗിക്കാൻ ഞാൻ തീരുമാനിച്ചു, അതായത് ലൂപ്പിന്റെ തുടക്കത്തിലേക്ക് കുതിക്കുന്നതിന് മുമ്പ് എട്ട് ലൂപ്പ് ഓപ്പറേഷനുകൾ സ്വമേധയാ ചെയ്യുക. ഈ ഒപ്റ്റിമൈസേഷൻ കോഡിലെ ബ്രാഞ്ചുകളുടെ എണ്ണം കുറയ്ക്കുന്നു, കൂടാതെ ലഭ്യമായ സൌജന്യ രജിസ്റ്ററുകളുടെ എണ്ണത്തിൽ ഇത് പരിമിതപ്പെടുത്തിയിരിക്കുന്നു.
ശരി, പ്രകടനത്തെക്കുറിച്ച്? അവൾ സുന്ദരിയാണ്! മികച്ച Go സൊല്യൂഷനുമായി താരതമ്യം ചെയ്യുമ്പോൾ ഞങ്ങൾ ഏഴ് മടങ്ങ് വേഗത കൈവരിച്ചു. ശ്രദ്ധേയമാണ്, അല്ലേ?
എന്നാൽ അന്വേഷണ ഷെഡ്യൂളറിനായി AVX-512, പ്രീഫെച്ചിംഗ് അല്ലെങ്കിൽ JIT (ജസ്റ്റ്-ഇൻ-ടൈം കംപൈലർ) ഉപയോഗിച്ച് ഈ നടപ്പാക്കൽ ത്വരിതപ്പെടുത്താൻ സാധ്യതയുണ്ട്. എന്നാൽ ഇത് തീർച്ചയായും ഒരു പ്രത്യേക റിപ്പോർട്ടിനുള്ള വിഷയമാണ്.
ബിറ്റ്മാപ്പ് സൂചികകളിലെ പ്രശ്നങ്ങൾ
Go-യിലെ ഒരു ബിറ്റ്മാപ്പ് സൂചികയുടെ ലളിതമായ നിർവ്വഹണവും അസംബ്ലി ഭാഷയിൽ കൂടുതൽ ഉൽപ്പാദനക്ഷമതയുള്ളതുമായ ഒരു ബിറ്റ്മാപ്പ് സൂചിക ഞങ്ങൾ ഇതിനകം പരിശോധിച്ചുകഴിഞ്ഞു, എന്തുകൊണ്ടാണ് ബിറ്റ്മാപ്പ് സൂചികകൾ വളരെ അപൂർവമായി ഉപയോഗിക്കുന്നത് എന്നതിനെക്കുറിച്ച് നമുക്ക് ഒടുവിൽ സംസാരിക്കാം.
പഴയ പേപ്പറുകൾ ബിറ്റ്മാപ്പ് സൂചികകളിലെ മൂന്ന് പ്രശ്നങ്ങൾ പരാമർശിക്കുന്നു, എന്നാൽ പുതിയ പേപ്പറുകളും അവയ്ക്ക് പ്രസക്തിയില്ലെന്ന് ഞാനും വാദിക്കുന്നു. ഈ ഓരോ പ്രശ്നങ്ങളിലും ഞങ്ങൾ ആഴത്തിൽ മുങ്ങുകയില്ല, മറിച്ച് അവയെ ഉപരിപ്ലവമായി നോക്കും.
ഉയർന്ന കാർഡിനാലിറ്റിയുടെ പ്രശ്നം
അതിനാൽ, കുറഞ്ഞ കാർഡിനാലിറ്റി ഉള്ള ഫീൽഡുകൾക്ക് മാത്രമേ ബിറ്റ്മാപ്പ് സൂചികകൾ അനുയോജ്യമാകൂ എന്ന് ഞങ്ങളോട് പറയപ്പെടുന്നു, അതായത്, കുറച്ച് മൂല്യങ്ങളുള്ളവ (ഉദാഹരണത്തിന്, ലിംഗഭേദം അല്ലെങ്കിൽ കണ്ണ് നിറം), കാരണം അത്തരം ഫീൽഡുകളുടെ സാധാരണ പ്രാതിനിധ്യം (ഒന്ന് ബിറ്റ് പെർ വാല്യു) ഉയർന്ന കാർഡിനാലിറ്റിയുടെ കാര്യത്തിൽ, അത് വളരെയധികം ഇടം എടുക്കും, കൂടാതെ, ഈ ബിറ്റ്മാപ്പ് സൂചികകൾ മോശമായി (അപൂർവ്വമായി) നിറയും.
സംഖ്യകളെ പ്രതിനിധീകരിക്കാൻ ഉപയോഗിക്കുന്ന സ്റ്റാൻഡേർഡ് പോലെയുള്ള മറ്റൊരു പ്രാതിനിധ്യം ചിലപ്പോൾ നമ്മൾ ഉപയോഗിച്ചേക്കാം. എന്നാൽ എല്ലാം മാറ്റിമറിച്ചത് കംപ്രഷൻ അൽഗോരിതങ്ങളുടെ വരവായിരുന്നു. കഴിഞ്ഞ ദശകങ്ങളിൽ, ശാസ്ത്രജ്ഞരും ഗവേഷകരും ബിറ്റ്മാപ്പുകൾക്കായി ധാരാളം കംപ്രഷൻ അൽഗോരിതങ്ങൾ കൊണ്ടുവന്നിട്ടുണ്ട്. ബിറ്റ് പ്രവർത്തനങ്ങൾ നടത്താൻ ബിറ്റ്മാപ്പുകൾ ഡീകംപ്രസ്സ് ചെയ്യേണ്ട ആവശ്യമില്ല എന്നതാണ് അവരുടെ പ്രധാന നേട്ടം - കംപ്രസ് ചെയ്ത ബിറ്റ്മാപ്പുകളിൽ നമുക്ക് ബിറ്റ് പ്രവർത്തനങ്ങൾ നേരിട്ട് നടത്താം.
അടുത്തിടെ, അലറുന്ന ബിറ്റ്മാപ്പുകൾ പോലെയുള്ള ഹൈബ്രിഡ് സമീപനങ്ങൾ പ്രത്യക്ഷപ്പെടാൻ തുടങ്ങി. ബിറ്റ്മാപ്പുകൾക്കായി അവർ ഒരേസമയം മൂന്ന് വ്യത്യസ്ത പ്രാതിനിധ്യങ്ങൾ ഉപയോഗിക്കുന്നു - ബിറ്റ്മാപ്പുകൾ, അറേകൾ, ബിറ്റ് റൺ എന്ന് വിളിക്കപ്പെടുന്നവ - കൂടാതെ പ്രകടനം വർദ്ധിപ്പിക്കുന്നതിനും മെമ്മറി ഉപഭോഗം കുറയ്ക്കുന്നതിനും അവയ്ക്കിടയിൽ ബാലൻസ് ചെയ്യുന്നു.
ഏറ്റവും ജനപ്രിയമായ ആപ്ലിക്കേഷനുകളിൽ നിങ്ങൾക്ക് അലറുന്ന ബിറ്റ്മാപ്പുകൾ കണ്ടെത്താനാകും. Go-യ്ക്കായുള്ള മൂന്നിലധികം നിർവ്വഹണങ്ങൾ ഉൾപ്പെടെ, വൈവിധ്യമാർന്ന പ്രോഗ്രാമിംഗ് ഭാഷകൾക്കായി ഇതിനകം തന്നെ ധാരാളം നടപ്പിലാക്കലുകൾ ഉണ്ട്.
ഉയർന്ന കാർഡിനാലിറ്റി കൈകാര്യം ചെയ്യാൻ നമ്മെ സഹായിക്കുന്ന മറ്റൊരു സമീപനത്തെ ബിന്നിംഗ് എന്ന് വിളിക്കുന്നു. ഒരു വ്യക്തിയുടെ ഉയരത്തെ പ്രതിനിധീകരിക്കുന്ന ഒരു ഫീൽഡ് നിങ്ങൾക്കുണ്ടെന്ന് സങ്കൽപ്പിക്കുക. ഉയരം ഒരു ഫ്ലോട്ടിംഗ് പോയിന്റ് നമ്പറാണ്, എന്നാൽ നമ്മൾ മനുഷ്യർ അത് അങ്ങനെ ചിന്തിക്കുന്നില്ല. ഞങ്ങളെ സംബന്ധിച്ചിടത്തോളം ഉയരം 185,2 സെന്റിമീറ്ററും 185,3 സെന്റിമീറ്ററും തമ്മിൽ വ്യത്യാസമില്ല.
സമാന മൂല്യങ്ങളെ 1 സെന്റിമീറ്ററിനുള്ളിൽ ഗ്രൂപ്പുകളായി ഗ്രൂപ്പുചെയ്യാൻ കഴിയുമെന്ന് ഇത് മാറുന്നു.
വളരെ കുറച്ച് ആളുകൾക്ക് 50 സെന്റിമീറ്ററിൽ താഴെയും 250 സെന്റിമീറ്ററിൽ കൂടുതൽ ഉയരവും ഉണ്ടെന്ന് നമുക്കറിയാമെങ്കിൽ, അനന്തമായ കാർഡിനാലിറ്റി ഉള്ള ഒരു ഫീൽഡിനെ 200 മൂല്യങ്ങളുള്ള ഒരു ഫീൽഡാക്കി മാറ്റാം.
തീർച്ചയായും, ആവശ്യമെങ്കിൽ, ഞങ്ങൾക്ക് പിന്നീട് അധിക ഫിൽട്ടറിംഗ് നടത്താം.
ഉയർന്ന ബാൻഡ്വിഡ്ത്ത് പ്രശ്നം
ബിറ്റ്മാപ്പ് സൂചികകളുടെ അടുത്ത പ്രശ്നം, അവ അപ്ഡേറ്റ് ചെയ്യുന്നത് വളരെ ചെലവേറിയതാണ് എന്നതാണ്.
നൂറുകണക്കിന് മറ്റ് അന്വേഷണങ്ങൾ ഡാറ്റ തിരയുമ്പോൾ ഡാറ്റാബേസുകൾക്ക് ഡാറ്റ അപ്ഡേറ്റ് ചെയ്യാൻ കഴിയണം. സമകാലിക ഡാറ്റ ആക്സസ് അല്ലെങ്കിൽ മറ്റ് പങ്കിടൽ പ്രശ്നങ്ങളിലുള്ള പ്രശ്നങ്ങൾ ഒഴിവാക്കാൻ ഞങ്ങൾക്ക് ലോക്കുകൾ ആവശ്യമാണ്. ഒരു വലിയ പൂട്ട് ഉള്ളിടത്ത് ഒരു പ്രശ്നമുണ്ട് - ലോക്ക് തർക്കം, ഈ പൂട്ട് ഒരു തടസ്സമാകുമ്പോൾ.
ഷാർഡിംഗ് ഉപയോഗിച്ചോ പതിപ്പിച്ച സൂചികകൾ ഉപയോഗിച്ചോ ഈ പ്രശ്നം പരിഹരിക്കാനോ ഒഴിവാക്കാനോ കഴിയും.
ഷാർഡിംഗ് എന്നത് ലളിതവും അറിയപ്പെടുന്നതുമായ കാര്യമാണ്. മറ്റേതൊരു ഡാറ്റയും പോലെ നിങ്ങൾക്ക് ഒരു ബിറ്റ്മാപ്പ് സൂചിക പങ്കിടാം. ഒരു വലിയ പൂട്ടിന് പകരം, നിങ്ങൾക്ക് ഒരു കൂട്ടം ചെറിയ പൂട്ടുകൾ ലഭിക്കും, അങ്ങനെ ലോക്ക് തർക്കത്തിൽ നിന്ന് മുക്തി നേടാം.
പ്രശ്നം പരിഹരിക്കാനുള്ള രണ്ടാമത്തെ മാർഗം പതിപ്പ് ഇൻഡെക്സുകൾ ഉപയോഗിക്കുക എന്നതാണ്. നിങ്ങൾ തിരയുന്നതിനോ വായിക്കുന്നതിനോ ഉപയോഗിക്കുന്ന സൂചികയുടെ ഒരു പകർപ്പും എഴുതുന്നതിനോ അപ്ഡേറ്റുചെയ്യുന്നതിനോ ഉപയോഗിക്കുന്ന ഒന്ന് നിങ്ങൾക്ക് സ്വന്തമാക്കാം. ഒരു നിശ്ചിത കാലയളവിൽ ഒരിക്കൽ (ഉദാഹരണത്തിന്, ഓരോ 100 ms അല്ലെങ്കിൽ 500 ms ഒരിക്കൽ) നിങ്ങൾ അവ ഡ്യൂപ്ലിക്കേറ്റ് ചെയ്ത് സ്വാപ്പ് ചെയ്യുന്നു. തീർച്ചയായും, ഈ സമീപനം നിങ്ങളുടെ അപ്ലിക്കേഷന് അൽപ്പം പിന്നിലുള്ള തിരയൽ സൂചിക കൈകാര്യം ചെയ്യാൻ കഴിയുന്ന സന്ദർഭങ്ങളിൽ മാത്രമേ ബാധകമാകൂ.
ഈ രണ്ട് സമീപനങ്ങളും ഒരേസമയം ഉപയോഗിക്കാനാകും: നിങ്ങൾക്ക് ഒരു ഷാർഡ് വേർഷൻ ഇൻഡെക്സ് ഉണ്ടായിരിക്കാം.
കൂടുതൽ സങ്കീർണ്ണമായ ചോദ്യങ്ങൾ
ബിറ്റ്മാപ്പ് സൂചികകളിലെ അവസാന പ്രശ്നം, സ്പാൻ അന്വേഷണങ്ങൾ പോലെയുള്ള കൂടുതൽ സങ്കീർണ്ണമായ ചോദ്യങ്ങൾക്ക് അവ അനുയോജ്യമല്ലെന്ന് ഞങ്ങളോട് പറയപ്പെടുന്നു എന്നതാണ്.
തീർച്ചയായും, നിങ്ങൾ അതിനെക്കുറിച്ച് ചിന്തിക്കുകയാണെങ്കിൽ, AND, OR, മുതലായ ബിറ്റ് പ്രവർത്തനങ്ങൾ "ഒരു രാത്രിക്ക് 200 മുതൽ 300 ഡോളർ വരെ റൂം നിരക്കുള്ള ഹോട്ടലുകൾ കാണിക്കൂ" എന്ന ചോദ്യത്തിന് അത്ര അനുയോജ്യമല്ല.
നിഷ്കളങ്കവും ബുദ്ധിശൂന്യവുമായ ഒരു പരിഹാരം ഓരോ ഡോളർ മൂല്യത്തിനും ഫലങ്ങൾ എടുത്ത് അവയെ ഒരു ബിറ്റ്വൈസ് അല്ലെങ്കിൽ ഓപ്പറേഷനുമായി സംയോജിപ്പിക്കുക എന്നതാണ്.
ഗ്രൂപ്പിംഗ് ഉപയോഗിക്കുന്നതാണ് അൽപ്പം മികച്ച പരിഹാരം. ഉദാഹരണത്തിന്, 50 ഡോളറിന്റെ ഗ്രൂപ്പുകളിൽ. ഇത് ഞങ്ങളുടെ പ്രക്രിയയെ 50 മടങ്ങ് വേഗത്തിലാക്കും.
എന്നാൽ ഇത്തരത്തിലുള്ള അഭ്യർത്ഥനയ്ക്കായി പ്രത്യേകം സൃഷ്ടിച്ച ഒരു കാഴ്ച ഉപയോഗിച്ച് പ്രശ്നം എളുപ്പത്തിൽ പരിഹരിക്കപ്പെടും. ശാസ്ത്രീയ പേപ്പറുകളിൽ ഇതിനെ ശ്രേണി-എൻകോഡഡ് ബിറ്റ്മാപ്പുകൾ എന്ന് വിളിക്കുന്നു.
ഈ പ്രാതിനിധ്യത്തിൽ, ഞങ്ങൾ ചില മൂല്യങ്ങൾക്കായി ഒരു ബിറ്റ് സജ്ജീകരിക്കുന്നില്ല (ഉദാഹരണത്തിന്, 200), എന്നാൽ ഈ മൂല്യവും എല്ലാം ഉയർന്നതും സജ്ജമാക്കുക. 200 ഉം അതിനുമുകളിലും. 300: 300-ഉം അതിനുമുകളിലും സമാനമാണ്. ഇത്യാദി.
ഈ പ്രാതിനിധ്യം ഉപയോഗിച്ച്, സൂചികയിൽ രണ്ട് പ്രാവശ്യം സഞ്ചരിക്കുന്നതിലൂടെ ഇത്തരത്തിലുള്ള തിരയൽ ചോദ്യത്തിന് നമുക്ക് ഉത്തരം നൽകാം. ആദ്യം, മുറിക്ക് 300 ഡോളറോ കുറവോ ഉള്ള ഹോട്ടലുകളുടെ ഒരു ലിസ്റ്റ് ലഭിക്കും, തുടർന്ന് റൂം ചെലവ് കുറഞ്ഞതോ $199 ആയതോ ആയ ഹോട്ടലുകൾ ഞങ്ങൾ അതിൽ നിന്ന് നീക്കം ചെയ്യും. തയ്യാറാണ്.
നിങ്ങൾ ആശ്ചര്യപ്പെടും, പക്ഷേ ബിറ്റ്മാപ്പ് സൂചികകൾ ഉപയോഗിച്ച് ജിയോക്വറികൾ പോലും സാധ്യമാണ്. ഒരു ജ്യാമിതീയ രൂപവുമായി നിങ്ങളുടെ കോർഡിനേറ്റിനെ ചുറ്റിപ്പറ്റിയുള്ള ഒരു ജ്യാമിതീയ പ്രാതിനിധ്യം ഉപയോഗിക്കുന്നതാണ് തന്ത്രം. ഉദാഹരണത്തിന്, Google-ൽ നിന്നുള്ള S2. അക്കമിടാൻ കഴിയുന്ന മൂന്നോ അതിലധികമോ വിഭജിക്കുന്ന വരികളുടെ രൂപത്തിൽ പ്രതിനിധീകരിക്കാൻ ചിത്രം സാധ്യമായിരിക്കണം. ഇതുവഴി നമ്മുടെ ജിയോക്വറിയെ "വിടവിലൂടെ" (ഈ അക്കമിട്ട വരികളിലൂടെ) നിരവധി ചോദ്യങ്ങളാക്കി മാറ്റാം.
റെഡി സൊല്യൂഷൻസ്
എനിക്ക് നിങ്ങളോട് അൽപ്പം താൽപ്പര്യമുണ്ടെന്ന് ഞാൻ പ്രതീക്ഷിക്കുന്നു, നിങ്ങളുടെ ആയുധപ്പുരയിൽ ഇപ്പോൾ നിങ്ങൾക്ക് മറ്റൊരു ഉപയോഗപ്രദമായ ഉപകരണം ഉണ്ട്. നിങ്ങൾക്ക് എപ്പോഴെങ്കിലും ഇതുപോലെ എന്തെങ്കിലും ചെയ്യേണ്ടി വന്നാൽ, ഏത് വഴിയാണ് നോക്കേണ്ടതെന്ന് നിങ്ങൾക്കറിയാം.
എന്നിരുന്നാലും, ആദ്യം മുതൽ ബിറ്റ്മാപ്പ് സൂചികകൾ സൃഷ്ടിക്കാൻ എല്ലാവർക്കും സമയമോ ക്ഷമയോ വിഭവങ്ങളോ ഇല്ല. പ്രത്യേകിച്ചും കൂടുതൽ വിപുലമായവ, ഉദാഹരണത്തിന് SIMD ഉപയോഗിക്കുന്നു.
ഭാഗ്യവശാൽ, നിങ്ങളെ സഹായിക്കാൻ നിരവധി റെഡിമെയ്ഡ് പരിഹാരങ്ങളുണ്ട്.
അലറുന്ന ബിറ്റ്മാപ്പുകൾ
ഒന്നാമതായി, ഞാൻ ഇതിനകം സംസാരിച്ച അതേ അലറുന്ന ബിറ്റ്മാപ്സ് ലൈബ്രറിയുണ്ട്. നിങ്ങൾ ഒരു പൂർണ്ണമായ ബിറ്റ്മാപ്പ് സൂചിക സൃഷ്ടിക്കേണ്ട ആവശ്യമായ എല്ലാ കണ്ടെയ്നറുകളും ബിറ്റ് പ്രവർത്തനങ്ങളും ഇതിൽ അടങ്ങിയിരിക്കുന്നു.
നിർഭാഗ്യവശാൽ, ഇപ്പോൾ, Go നടപ്പിലാക്കലുകളൊന്നും SIMD ഉപയോഗിക്കുന്നില്ല, അതിനർത്ഥം Go നടപ്പിലാക്കലുകൾ C നടപ്പിലാക്കലുകളേക്കാൾ പ്രകടനം കുറവാണ്, ഉദാഹരണത്തിന്.
പിലോസ
നിങ്ങളെ സഹായിക്കുന്ന മറ്റൊരു ഉൽപ്പന്നം Pilosa DBMS ആണ്, വാസ്തവത്തിൽ ബിറ്റ്മാപ്പ് സൂചികകൾ മാത്രമാണുള്ളത്. ഇത് താരതമ്യേന പുതിയ ഒരു പരിഹാരമാണ്, പക്ഷേ ഇത് വളരെ വേഗത്തിൽ ഹൃദയങ്ങളെ കീഴടക്കുന്നു.
Pilosa ആന്തരികമായി അലറുന്ന ബിറ്റ്മാപ്പുകൾ ഉപയോഗിക്കുകയും അവ ഉപയോഗിക്കാനുള്ള കഴിവ് നൽകുകയും ഞാൻ മുകളിൽ സംസാരിച്ച എല്ലാ കാര്യങ്ങളും ലളിതമാക്കുകയും വിശദീകരിക്കുകയും ചെയ്യുന്നു: ഗ്രൂപ്പിംഗ്, റേഞ്ച്-എൻകോഡ് ചെയ്ത ബിറ്റ്മാപ്പുകൾ, ഒരു ഫീൽഡിന്റെ ആശയം മുതലായവ.
നിങ്ങൾക്ക് ഇതിനകം പരിചിതമായ ഒരു ചോദ്യത്തിന് ഉത്തരം നൽകാൻ Pilosa ഉപയോഗിക്കുന്നതിന്റെ ഒരു ഉദാഹരണം നമുക്ക് പെട്ടെന്ന് നോക്കാം.
നിങ്ങൾ മുമ്പ് കണ്ടതിന് സമാനമാണ് ഉദാഹരണം. ഞങ്ങൾ Pilosa സെർവറിലേക്ക് ഒരു ക്ലയന്റ് സൃഷ്ടിക്കുന്നു, ഒരു സൂചികയും ആവശ്യമായ ഫീൽഡുകളും സൃഷ്ടിക്കുന്നു, തുടർന്ന് പ്രോബബിലിറ്റികളുള്ള ക്രമരഹിതമായ ഡാറ്റ ഉപയോഗിച്ച് ഞങ്ങളുടെ ഫീൽഡുകൾ പൂരിപ്പിക്കുകയും, ഒടുവിൽ, പരിചിതമായ അന്വേഷണം നടപ്പിലാക്കുകയും ചെയ്യുന്നു.
അതിനുശേഷം, "ചെലവേറിയ" ഫീൽഡിൽ ഞങ്ങൾ NOT ഉപയോഗിക്കും, തുടർന്ന് "ടെറസ്" ഫീൽഡും "റിസർവേഷൻ" ഫീൽഡും ഉപയോഗിച്ച് ഫലം (അല്ലെങ്കിൽ അത്) വിഭജിക്കുക. ഒടുവിൽ, നമുക്ക് അന്തിമ ഫലം ലഭിക്കും.
ഭാവിയിൽ MySQL, PostgreSQL - ബിറ്റ്മാപ്പ് സൂചികകൾ പോലുള്ള DBMS-കളിലും ഈ പുതിയ തരം സൂചിക ദൃശ്യമാകുമെന്ന് ഞാൻ ശരിക്കും പ്രതീക്ഷിക്കുന്നു.
തീരുമാനം
നിങ്ങൾ ഇതുവരെ ഉറങ്ങിയിട്ടില്ലെങ്കിൽ, നന്ദി. പരിമിതമായ സമയമായതിനാൽ എനിക്ക് പല വിഷയങ്ങളിലും ഹ്രസ്വമായി സ്പർശിക്കേണ്ടി വന്നു, പക്ഷേ സംഭാഷണം ഉപയോഗപ്രദവും ഒരുപക്ഷേ പ്രചോദിപ്പിക്കുന്നതുമാകുമെന്ന് ഞാൻ പ്രതീക്ഷിക്കുന്നു.
ബിറ്റ്മാപ്പ് സൂചികകൾ നിങ്ങൾക്ക് ഇപ്പോൾ ആവശ്യമില്ലെങ്കിൽപ്പോലും അറിയുന്നത് നല്ലതാണ്. അവ നിങ്ങളുടെ ടൂൾബോക്സിലെ മറ്റൊരു ഉപകരണമായിരിക്കട്ടെ.
Go-യുടെ വിവിധ പ്രകടന തന്ത്രങ്ങളും Go കംപൈലർ ഇതുവരെ നന്നായി കൈകാര്യം ചെയ്യാത്ത കാര്യങ്ങളും ഞങ്ങൾ പരിശോധിച്ചു. എന്നാൽ ഇത് ഓരോ Go പ്രോഗ്രാമർക്കും അറിയാൻ തികച്ചും ഉപയോഗപ്രദമാണ്.
എനിക്ക് നിങ്ങളോട് പറയാൻ ആഗ്രഹിച്ചത് ഇത്രമാത്രം. നന്ദി!
അവലംബം: www.habr.com