ããã«ã¡ã¯ãç§ã®ååã¯Sashaã§ããææ°ã®x86ããã»ããµåãã®æéã®ç»åãµã€ãºå€æŽãæžããŸããã ç§ãèŠã€ããŠãã¹ãããä»ã®ãã¹ãŠã®ã©ã€ãã©ãªãé ãã®ã§ãç§ã¯ããèšããŸãã Uploadcareã§ãªã³ã¶ãã©ã€ã§ç»åã®ãµã€ãºå€æŽãæé©åããäœæ¥ãããŠãããšãã«ããã®ã¿ã¹ã¯ãåããŸããã ã³ãŒããéãããšã«ããŸããããã®çµæã Pillow-SIMDãããžã§ã¯ããç»å ŽããŸããã 誰ã§ãç°¡åã«Pythonã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšã§ããŸãã
ã³ãŒãã¯ç¹å®ã®ããŒããŠã§ã¢ã§å®è¡ãããã¢ãŒããã¯ãã£ãç解ããããšã«ãã£ãŠã®ã¿æé©ãªæé©åãéæã§ããŸãã åèšã§4ã5件ã®èšäºããªãªãŒã¹ããéã®ã¢ãŒããã¯ãã£ã«é¢ããç¥èãé©çšããŠå®éã®ã¿ã¹ã¯ãæé©åããæ¹æ³ã説æããŸãã ç§ã®äŸã§ã¯ãä»ã®ã¢ããªã±ãŒã·ã§ã³ãæé©åããããšããå§ãããŸãã æåã®2ã€ã®èšäºã¯1é±é以å ã«å ¬éãããæ®ãã¯å ¬éãããŸãã
ã¿ã¹ã¯ã«ã€ããŠ
ãç»åã®ãµã€ãºå€æŽããšã¯ãç³ã¿èŸŒã¿ãªãµã³ããªã³ã°ã䜿çšããŠç»åã®ãµã€ãºãå€æŽããããšãæå³ããŸãã ãªãµã³ããªã³ã°ã¯ãç»åã®ãã³ãŒããšãšã³ã³ãŒããèæ ®ããã«ã8ãããRGBãã¯ã»ã«ã®é åãä»ããŠã¡ã¢ãªã«å®è¡ãããŸãããæçµç»åã®ã¡ã¢ãªã®å²ãåœãŠãèæ ®ããç¹å®ã®æäœã«å¿ èŠãªä¿æ°ã®æºåãèæ ®ããŸãã
ããã¯ãšãŠãå³ããã§ãã ããªãã¯ïŒãžãŒãããå°ããªç»åããã³ãŒããããªã©ïŒãã¢ã«ãŽãªãºã ã®çµã¿åããã¯ãªããç¹å®ã®ã¢ã«ãŽãªãºã ã®åäœãæ£çŽã«æž¬å®ããã ãã§ãã ç¹æ®ãªã±ãŒã¹ã®ããªãã¯ãšæé©åã¯åŸã§é©çšã§ããŸããããããã¯ãã®ã·ãªãŒãºã®èšäºã§æ€èšãã察象ã§ã¯ãããŸããã
...ç³ã¿èŸŒã¿ãªãµã³ããªã³ã°ã䜿çšããŸãã ãªã«ïŒ
æé©åãç¹ã«å¿ èŠãªãã®ãæ確ã«ããããã«ãç³ã¿èŸŒã¿ãªãµã³ããªã³ã°ãšã¯äœãã説æããŸãã ç³ã¿èŸŒã¿ïŒæ£ç¢ºã«èšãã°ã é¢æ£å€ã®ç³ã¿èŸŒã¿ã¯ ãç»åã®ãã¯ã»ã«ãé¢æ£çã§ããããïŒã¯éåžžã«ç°¡åãªæ°åŠçæäœã§ãã äžé£ã®å€No. 1ïŒä¿æ°ïŒãšäžé£ã®å€No. 2ïŒããŒã¿ããã®å Žåã¯ãã¯ã»ã«ãã£ãã«ã®åŒ·åºŠïŒããããŸãã ãããã®2ã€ã®è¡ã®ç³ã¿èŸŒã¿ã®çµæã¯ããã¢ã®ãã¹ãŠã®ã¡ã³ããŒã®ç©ã®åèšã«ãªããŸãã ãšãŠãã·ã³ãã«-ããŒã¹ã®åèšã ãã¿ã³ã¯åœŒãå§ããåã«çµãã£ãã
ãã®æäœããµã€ãºå€æŽã«ã©ã®ããã«é¢é£ä»ããããããæ£ç¢ºã«ç解ããå¿ èŠããããŸãã äžé£ã®å€No. 2ã¯ãå ã®ç»åã®äžé£ã®ãã¯ã»ã«ã§ãã å€ãã®å€1ã¯ããã£ã«ã¿ãŒããåŸãããä¿æ°ã§ãã ãã£ã«ã¿ãŒã¯ãå€ãã©ã®çšåºŠæ£ç¢ºã«çž®å°ãããã決å®ããé¢æ°ã§ãã PhotoshopãŸãã¯å¥ã®ã°ã©ãã£ãã¯ãšãã£ã¿ãŒïŒãã€ãªãã¢ããã€ãã¥ãŒããã¯ãå Žåã«ãã£ãŠã¯ã©ã³ãã§ã¹ïŒã®ãµã€ãºå€æŽãŠã£ã³ããŠã«ãã£ã«ã¿ãŒã®ããããããããŠã³ã¡ãã¥ãŒã«æ°ä»ãããããããŸããã ããããã®ãã£ã«ã¿ãŒã§ãã ãã ããç³ã¿èŸŒã¿ã®çµæã®å€ã¯ãæçµç»åã®1ãã¯ã»ã«ã®1ãã£ãã«ã®åŒ·åºŠã§ãã ã€ãŸã MÃNãã¯ã»ã«ã®ç»åãååŸããã«ã¯ãMÃNÃCã®ç³ã¿èŸŒã¿æŒç®ãè¡ãå¿ èŠããããŸããCã¯ã«ã©ãŒãã£ã³ãã«ã®æ°ã§ãã ã¯ãã1åã®æäœã§ãã¯ã»ã«å šäœãã«ãŠã³ãããããšã¯ã§ããŸãããç°ãªããã£ãã«ã®å€ã¯ç¬ç«ããŠãããåå¥ã«èæ ®ããå¿ èŠããããŸãã
ãã£ã«ã¿ãŒã®æ©èœã¯ç¡éã§ã¯ãªãããã®å€ã¯äžå€®éšåã§ã®ã¿ãŒãã§ã¯ãããŸããããã€ãªãã¢ãã£ã«ã¿ãŒã®å Žåãããã¯-1ã1ã®å€ã®ç¯å²ã§ãã â2ãã2ã®ãã€ãã¥ãŒããã¯ã®å Žåâ3ãã3ã®ã©ã³ãã§ã¹ã®å ŽåïŒãã ããä»ã®çš®é¡ã®ã©ã³ãã§ã¹ããããŸãïŒã
ãããã®æ°å€ã¯ãã£ã«ã¿ãŒãŠã£ã³ããŠãšåŒã°ããŸãã ãã£ã«ã¿ã¯ãã®ç¯å²ã§ã®ã¿é©çšãããå€åŽã§ã¯ãŒãã«çãããªããŸãã ãããã£ãŠãç³ã¿èŸŒã¿ã«å¿
èŠãªãœãŒã¹ãã¯ã»ã«ã®æ°ã¯ããã£ã«ã¿ãŒãŠã£ã³ããŠã®ãµã€ãºã«çž®å°ä¿æ°ïŒãŸãã¯å¢å ãçºçããå Žåã¯1ïŒãæããååŸã§ååŸãããŸãã ããã¯äŸã«ãã£ãŠæããã説æããããšæããŸãã ãã€ãã¥ãŒããã¯ãã£ã«ã¿ã䜿çšããŠã2560ãã¯ã»ã«ã®å¹
ã®ç»åã2048ã®å¹
ã«çž®å°ããå¿
èŠããããŸãã æçµç»åã®33çªç®ã®ãã¯ã»ã«ã®å€ãæ€çŽ¢ãããšããŸãã ãã€ãã¥ãŒããã¯ãã£ã«ã¿ãŒã®ãŠã£ã³ããŠãµã€ãºã¯2ã§ãçž®å°ä¿æ°ã¯2560/2048 = 1.25ã§ãããããå
ã®ç»åã®ãã¯ã»ã«ã®è¡ãfloor((33 - 2) à 1,25)
33-2 floor((33 - 2) Ã 1,25)
ããceil((33 + 2) Ã 1,25)
ãŸã§ååŸããå¿
èŠããããŸãceil((33 + 2) à 1,25)
ã ã€ãŸã 38çªç®ãã44çªç®ã®ãã¯ã»ã«ãŸã§ã åããã¯ã»ã«ã«ã€ããŠãä¿æ°å€ãèšç®ãããŸãã
ãã®ç¬éãŸã§ãç§ã¯ç»åãå®éã«äºæ¬¡å æ§é ã§ãããšããäºå®ãèŠæž¡ããªãããããã€ãã®ä¿æ°ãšããã€ãã®ãã¯ã»ã«ã«ã€ããŠè©±ããŸããã ãããŠãè«ççã«ã¯ãç·ã§ã¯ãªãå ã®ç»åã®äžéšãæããããå¿ èŠãããããã§ãã ãã ããç³ã¿èŸŒã¿ã®ç¹æ§ã®1ã€ã¯ãæäœãåçŽæ¹åãšæ°Žå¹³æ¹åã«å¥ã ã«å®è¡ããŠ2ã€ã®ãã¹ãäœæã§ããããšã§ãã 倧ãŸãã«èšããšãããã«ããOïŒn²ïŒããOïŒ2nïŒãžã®1ã€ã®ç³ã¿èŸŒã¿ã®è€éãã軜æžãããŸãïŒå®éã«ã¯ãããããå°ãªãã§ãããäŸç¶ãšããŠéèŠã§ãïŒã
ãªããã¹ãŠåãç³ã¿èŸŒã¿
äžè¬ã«ããã€ã¡ãŒãžã®ãµã€ãºå€æŽããšããèªå¥ã«ã¯ãå®è¡ããå¿ èŠãããæ å ±ã«é¢ããæå°éã®æ å ±ãå«ãŸããŠããŸãã 圌女ã¯ãæããããªããžã§ã¯ãã®ãžãªã¡ããªãç¶æããªããããªãªãžãã«ã䜿çšããŠæéãµã€ãºã®ç»åãååŸããå¿ èŠããããšèšããŸãã ãã ããå ã®ç»åã¯ããŸããŸãªæ¹æ³ã§äœ¿çšã§ããŸãã ããšãã°ãæçµãã¯ã»ã«ããšã«ãå ã®ãã¯ã»ã«ãã1ã€ã®ãã¯ã»ã«ããããããŠãå€æŽããã«äœ¿çšã§ããŸãã ããã¯æè¿åæ³ãšåŒã°ããŸãã çµµã¯èããç Žããäžå¿«ã§ãïŒ
ããã¯ãå ã®ãã¯ã»ã«ã®ããäžéšãæçµç»åã§äœ¿çšãããããã§ãïŒäžèšã®äŸã§ã¯ã1ïŒ æªæºïŒã æçµç»åã«å ¥ããªããã¯ã»ã«ã®æ å ±ã¯å€±ãããŸããã
ç³ã¿èŸŒã¿ã«ãããªãµã³ããªã³ã°ã¯æ¬¡ã®ããã«ãªããŸãã
ç³ã¿èŸŒã¿ã®ãªãµã³ããªã³ã°ã§ã¯ãæçµç»åã«å¯ŸããåãœãŒã¹ãã¯ã»ã«ã®å¯äžãæ£ããèæ ®ãããŸãã ããã¯æ®éçã ããã§ã åºç¯å²ã®ã¹ã±ãŒãªã³ã°ä¿æ°ã«å¯ŸããŠåçã«è¯å¥œã§äºæž¬å¯èœãªçµæãââæäŸããŸãããããŒã«ã«ã¬ãã«ã§ã®ãžãªã¡ããªã®æªã¿ã¯å«ãŸããŸããïŒäžéšã®ãã£ã«ã¿ã¯äŸç¶ãšããŠäžããããããã®ãããªæªã¿ãäžããªããã£ã«ã¿ã䜿çšããããšãã泚æäºé ããããŸãïŒã ãããŠäžè¬çã«ã1ã€ã®ããšãé€ããŠããã¹ãŠã®åŽé¢ããããã¯ãã¹ãŠéåžžã«æ£ç¢ºã§åªããŠããŸããããã©ãŒãã³ã¹ã§ãã
æ
Pillowã¯ãAlex ClarkãšEric Soroosãçããã³ãã¥ããã£ã«ãã£ãŠéçºãããPythonã€ã¡ãŒãžã©ã€ãã©ãªã§ãã Uploadcareã¯ãç§ãããŒã ã«å ããåããPillowã䜿çšããŠããŸããã ããããç§ã«ã¯å¥åŠã«æãã-ç»åãæ±ãããšã¯äž»èŠãªã¿ã¹ã¯ã®äžã€ã§ããããªãããã®ããã«èšèªã«çµã³ä»ããããã©ã€ãã©ãªãŒãåãå¿ èŠããã£ãã®ãã äœçŸäžäººãã®éçºè ã䜿çšããå€ãã®æ©èœãåããåãImageMagickã䜿çšããæ¹ãããã®ã§ã¯ãªãã§ããããã æ°å¹ŽåŸãç§ã«ãšã£ãŠãæã«ãšã£ãŠãæåãããšèšããŸãã çµå±ã®ãšãããæåã®æç¹ã§äž¡æ¹ã®ã©ã€ãã©ãªã®ããã©ãŒãã³ã¹ã¯ã»ãŒåãã§ããããç§ããããŒã®ããã«ããImageMagickã®ããã«äœããããåããããã©ããã¯éåžžã«çãããã§ãã
Pillowã¯ãéåžžã«å€ãPILã©ã€ãã©ãªã®ãã©ãŒã¯ã§ãã æŽå²çã«ãPILã§ã¯ãµã€ãºå€æŽã«ç³ã¿èŸŒã¿ã¯äœ¿çšãããŸããã§ããã PILã§ã®æåã®ç³ã¿èŸŒã¿ãµã€ãºå€æŽã®å®è£ ã¯ããŒãžã§ã³1.1.3ã§ç»å ŽããANTIALIASãã£ã«ã¿ãŒã䜿çšããŠå©çšã§ããŸãããANTIALIASãã£ã«ã¿ãŒã®ååã¯ãä»ã®ãã£ã«ã¿ãŒãäœå質ã®ã¢ã«ãŽãªãºã ã䜿çšãããšããäºå®ã匷調ããŸããã ãããã¯ãŒã¯äžã§ã¯ãPILïŒããã³æãšããŠãåä¿¡è ãšããŠïŒã®ãµã€ãºãå€æŽãããšãã«ANTIALIASãã£ã«ã¿ãŒã®ã¿ã䜿çšããé¢é£ããæšå¥šäºé ããªããªã£ãŠããããšããããããŸãã
æ®å¿µãªãããANTIALIASã®ããã©ãŒãã³ã¹ã¯ããªãäœãã£ãã ãœãŒã¹ã³ãŒãã調ã¹ãŠäœãã§ãããã確èªããŸããããANTIALIASã®ãµã€ãºå€æŽã®å®è£ ïŒã€ãŸããç³ã¿èŸŒã¿ïŒãæ®ãã®ãã£ã«ã¿ãŒã§äœ¿çšã§ããããšãããããŸããã ãŸããANTIALIASå®æ°èªäœã¯ã倧ããªãŠã£ã³ããŠïŒÂ±3ïŒãæã€Lanczosãã£ã«ã¿ãŒã«å¯Ÿå¿ãããããéåžžã«äœéã§ãã ç§ããããã£ãæåã®æé©åã¯ããã€ãªãã¢ãã£ã«ã¿ãŒãšãã€ãã¥ãŒããã¯ãã£ã«ã¿ãŒã®ç³ã¿èŸŒã¿ãæå¹ã«ããããšã§ããã ãã®ãããã¢ããªã±ãŒã·ã§ã³ã§å®äŸ¡ãªãã€ãã¥ãŒããã¯ãã£ã«ã¿ãŒã䜿çšããŠïŒÂ±2ã®ãŠã£ã³ããŠã䜿çšïŒãå質ãããŸãäœäžãããªãããã«ããããšãã§ããŸãã
ããã«ããµã€ãºå€æŽèªäœã®ã³ãŒããèŠãããšã«èå³ããããŸããã ãã®ã¢ãžã¥ãŒã«ã§ç°¡åã«èŠã€ããŸããã ãããŠãç§ã¯äž»ã«Pythonã§æžããŠããŸãããããã©ãŒãã³ã¹ã®é¢ã§ããã€ãã®çãããå Žæã«ããã«æ°ä»ããŸããã æ°åæé©åããåŸã2.5åã«ãªããŸããïŒããã«ã€ããŠã¯æ¬¡ã®èšäºã§èª¬æããŸã ïŒã ãã®åŸãSIMDãè©Šãããã¹ãŠã®èšç®ãæŽæ°ã«å€æãããµã€ã¯ã«ãšã°ã«ãŒãèšç®ãç©æ¥µçã«å±éãå§ããŸããã ãã®ã¿ã¹ã¯ã¯éåžžã«èå³æ·±ããã®ã§ãããçç£æ§ãåäžãããæ¹æ³ã«ã€ããŠãç§ã®é ã®äžã«ã¯åžžã«ããã€ãã®ã¢ã€ãã¢ããããŸããã ç§ã¯ãŠãµã®ã®ç©Žã«ã©ãã©ãæ·±ãå ¥ã蟌ã¿ãå¥ã®ä»®èª¬ãå®æçã«ãã¹ãããŸããã
åŸã ã«ãã³ãŒãã¯å€§ãããªããé«éã«ãªããŸããã ä»äºã®äžéšã¯æã«è¿ãããŸããã ããããSIMDã³ãŒãã¯ç¹å®ã®ã¢ãŒããã¯ãã£åãã«äœæããããã移æ€ãå°é£ã§ãããPillowã¯ã¯ãã¹ãã©ãããã©ãŒã ã©ã€ãã©ãªã§ãã ãããã£ãŠã Pillow-SIMDã®éã¯ãã¹ãã©ãŒã¯ãäœæããããšã決å®ãããŸããã Pillow-SIMDããŒãžã§ã³ã¯ãå ã®Pillowã®ããŒãžã§ã³ãšå®å šã«äžè²«ããŠãããäžéšã®æäœã«é床ãè¿œå ããŸãã
AVX2ãæèŒããPillow-SIMDã®ææ°ããŒãžã§ã³ã§ã¯ããªãµã€ãºã¯å ã®PILããã15ã30åé«éã§ãã åé ã§è¿°ã¹ãããã«ãããã¯ç§ããã¹ãããããšã«æåããé«å質ã®ãµã€ãºå€æŽã®æéã®å®è£ ã§ãã ããŸããŸãªã©ã€ãã©ãªã®ãã³ãããŒã¯ã®çµæãåéãããŠããããŒãžãèŠãããšãã§ããŸã ã
PillowãšPillow-SIMDã§ç§ãå¬ããã®ã¯ãããããåå¿è ã®éçºè ã§ãå®éã«äœ¿çšã§ããæ¬åœã®ã©ã€ãã©ãªã ãšããããšã§ãã ããã¯Stack Overflowã§å ¬éãããŠããã³ãŒãã®äžéšã§ã¯ãªããã©ãã«è²Œãä»ããããäžæ確ã§ãã ãããŠãåæäœãã³ã³ã¹ãã©ã¯ã¿ãŒãšããŠã¢ã»ã³ãã«ããå¿ èŠããããããªããã£ããããã¯ãã§ã¯ãããŸããã ããã«ã30åã³ã³ãã€ã«ããè€éãªã€ã³ã¿ãŒãã§ã€ã¹ãåããè€éãªC ++ã©ã€ãã©ãªããããŸããã ããã¯ã1è¡ã®ã€ã³ã¹ããŒã«è¡ã1è¡ã®ã©ã€ãã©ãªã€ã³ããŒãè¡ã1è¡ã®ã€ã¡ãŒãžèªã¿èŸŒã¿è¡ã§ããããã¡ãã£ãšããããèŠãŠãã¢ããªã±ãŒã·ã§ã³ã§æãéããµã€ãºå€æŽã䜿çšããŸããã§ãã
ããã©ãŒãã³ã¹æž¬å®
èšäºã§ã¯ããã€ãªãã¢ããã€ãã¥ãŒããã¯ãã©ã³ãã§ã¹ãã£ã«ã¿ãŒã䜿çšããŠã2560Ã1600ãã¯ã»ã«ã®è§£å床ã®å ã®ç»åã320x200ã2048x1280ã5478x3424ã®è§£å床ã«ãµã€ãºå€æŽãããããŒãã«åœ¢åŒã§ããã©ãŒãã³ã¹æž¬å®å€ãã¢ããããŒãããŸãïŒã€ãŸããåèš9ã€ã®æäœïŒã å ã®ç»åã¯ã第3ã¬ãã«ã®ããã»ããµã®ãã£ãã·ã¥ã«å®å šã«åãŸããªãã»ã©å€§ããåãããŸãã åæã«ãç»åã®å®éã®ã³ã³ãã³ãã¯ããã©ãŒãã³ã¹ã®ç¹ã§ã¯éèŠã§ã¯ãããŸãããå°ãªããšãçœç«ãé»ç«ãç«ã®åçã®ãµã€ãºãå€æŽã§ããŸãã 以äžã¯ãæé©ååã®PillowããŒãžã§ã³2.6ã©ã€ãã©ãªã®çµæã®äŸã§ãã
Scale 2560Ã1600 RGB image to 320x200 bil 0.08927 s 45.88 Mpx/s to 320x200 bic 0.13073 s 31.33 Mpx/s to 320x200 lzs 0.16436 s 24.92 Mpx/s to 2048x1280 bil 0.40833 s 10.03 Mpx/s to 2048x1280 bic 0.45507 s 9.00 Mpx/s to 2048x1280 lzs 0.52855 s 7.75 Mpx/s to 5478x3424 bil 1.49024 s 2.75 Mpx/s to 5478x3424 bic 1.84503 s 2.22 Mpx/s to 5478x3424 lzs 2.04901 s 2.00 Mpx/s
ããã®2çªç®ã®åã¯ç§åäœã®æéã§ã3çªç®ã®åã¯ãã®æäœã®å ã®ç»åã®åž¯åå¹ ã§ãã ã€ãŸããæäœã«0.2ç§ããã£ãå Žåãã¹ã«ãŒãããã¯2560Ã1600 / 0.2 = 20.48ã¡ã¬ãã¯ã»ã«/ç§ã«ãªããŸãã
å ã®ç»åã¯ã164ããªç§ã§320Ã200ã®è§£å床ã«ãµã€ãºå€æŽãããŸãã ãŸããã¡ãã£ãšæªããªãã æé©åããå¿ èŠã¯ãŸã£ãããªããããããŸãããããã®ãŸãŸã«ããŠãããŸããïŒ æºåž¯é»è©±ããã®åçã®è§£å床ãå¹³åããŠ12ã¡ã¬ãã¯ã»ã«ã«ãªã£ãããšãæãåºããšããã¹ãŠãããã»ã©ãã©è²ã§ã¯ãªãããšãããããŸãã iPhoneããã®åçã¯ãé梱ãèæ ®ããã«0.5ç§çž®å°ãããŸãã ä»ã®æäœãèæ ®ãããšã1åãããçŽ80æã1æéãããçŽ5000æã®ç»åãåŠçã§ããçŸåšã®ãµãŒãã¹ã®è² è·ã¯1æéãããçŽ13äžä»¶ã§ãã ãã®è² è·ãåŠçããã«ã¯ã26å°ã®AWS c4.largeãµãŒããŒãå¶éã§å®è¡ããå¿ èŠããããŸãã å®éã«ã¯ã4å°ã®ãµãŒããŒã®ã¿ãé¢äžããŠãããæãæéã§ã®è² è·ã¯çŽ40ïŒ ã§ãã
ãã®ãããªå¹æãææã®èŠæš¡ã«å€æ¿ããç»åã®ãµã€ãºãå€æŽãããã¹ãŠã®ã³ãŒããããå¹æçãªãã®ã«çœ®ãæããããšãã§ããã°ããã®æ©æµã¯the倧ã§ãã æ°äžå°ã®ãµãŒããŒãç¯çŽãããæ°çŸããã¯ããã®é»åãç¯çŽãããŸããã ãããŠãããã¯äžçã®æ¶è²»ã®100äžåã®1ã§ãã ã¯ããããªãã¯å°çãæãããšãã§ããŸãïŒ
æ¬¡ïŒ ããŒã1ãäžè¬çãªæé©å