рд╕реБрдиреНрди рдФрд░ рдбрд░рд╛рд╡рдирд╛ рдкреИрдХреЗрдЬ рд╡рд┐рднрд┐рдиреНрди рдХрдВрдкреНрдпреВрдЯрд┐рдВрдЧ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрддреНрдХреГрд╖реНрдЯ рд╕реБрд╡рд┐рдзрд╛рдПрдБ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдХрд╛рд░реНрдпреЛрдВ (ufunc) рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛, рд╕реНрдХреЗрд▓рд░ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдЖрдпрд╛рдореЛрдВ рдХреЗ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛, рдЖрдкрдХреЛ рдкрд╛рдпрдерди рднрд╛рд╖рд╛ рдореЗрдВ рдирд┐рд╣рд┐рдд рд╕рд╛рджрдЧреА рдФрд░ рд▓рд╛рд▓рд┐рддреНрдп рдХреЛ рдмрдирд╛рдП рд░рдЦрддреЗ рд╣реБрдП рдЙрдЪреНрдЪ рдкреНрд░рджрд░реНрд╢рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрдорддреМрд░ рдкрд░ рдПрдХ рдмрдбрд╝реЗ рдбреЗрдЯрд╛ рд╕реЗрдЯ рдкрд░ рдПрдХрд▓ рдСрдкрд░реЗрд╢рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдХрд┐
SIMD рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рдЖрджрд░реНрд╢ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдореБрдлреНрдд рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рддреИрдпрд╛рд░ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИ рдЬреЛ SIMD рдХрд╛ рдЙрдкрдпреЛрдЧ рдЧрдгрд┐рддреАрдп рдХрд╛рд░реНрдпреЛрдВ рдЬреИрд╕реЗ рдХрд┐ рд╕реБрдиреНрди рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рд╕рд╛рдЗрди, рдХреЛрд╕рд╛рдЗрди рдФрд░ рдШрд╛рддрд╛рдВрдХред рдореИрдВ рдЦрд░реЛрдВрдЪ рд╕реЗ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреА рдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рд╕реМрднрд╛рдЧреНрдп рд╕реЗ рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рд╕реА рднрд╛рд╖рд╛ рдореЗрдВ рдХрдИ рдореБрдлреНрдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рдереЗред рд╕рдВрджреЗрд╣ рдХреЗ
рдЖрд▓рд╕реНрдп рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЦрдЧреЛрд▓реАрдп-рдореЙрдбреНрдпреВрд▓ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рд╕рд╛рдЗрди, рдХреЛрд╕рд╛рдЗрди рдФрд░ рдкреНрд░рддрд┐рдкрд╛рджрдХ рдХреЗ рд▓рд┐рдП рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдХрд╛рд░реНрдп рдХреА рдкреЗрд╢рдХрд╢ рдХреАред рд╡рд┐рд╡рд░рдг рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЗ рд▓рд┐рдП, рдмрд┐рд▓реНрд▓реА рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред
SIMD рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕рд╛
SIMD рдирд┐рд░реНрджреЗрд╢ рдЖрдкрдХреЛ рдПрдХ рд╕рд╛рде рдПрдХ рд╣реА рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рдХрдИ рдирдВрдмрд░реЛрдВ рдкрд░ рдПрдХ рд╣реА рдСрдкрд░реЗрд╢рди рдХреЛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдПрдХ рдЪрдХреНрд░ рдореЗрдВ, рдЖрдк рдПрдХ рд╣реА рдмрд╛рд░ рдореЗрдВ рдХрдИ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рдХрдИ рдмрд╛рд░ рдЙрддреНрдкрд╛рджрдХрддрд╛ рдмрдврд╝рд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, SIMD рдЕрдиреБрджреЗрд╢ рд╕реЗрдЯ
рдЙрдиреНрдирдд рд╡реЗрдХреНрдЯрд░ рдПрдХреНрд╕рдЯреЗрдВрд╢рди (AVX) 256-рдмрд┐рдЯ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдЪрд╛рд▓рди рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЗрдВ рдЖрда 32-рдмрд┐рдЯ рдлрд╝реНрд▓реЛрдЯрд┐рдВрдЧ-рдкреЙрдЗрдВрдЯ рдирдВрдмрд░ (рдПрдХрд▓-рд╕рдЯреАрдХ рд╕рдВрдЦреНрдпрд╛), рдпрд╛ рдЪрд╛рд░ 64-рдмрд┐рдЯ (рдбрдмрд▓-рд╕рдЯреАрдХ рд╕рдВрдЦреНрдпрд╛) рд╢рд╛рдорд┐рд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ ред рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рд╕реЗрдЯ рдмрд▓реНрдХрд┐ рдорд╛рдореВрд▓реА рд╣реИ, рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдШрдЯрд╛рд╡, рдЧреБрдгрд╛ рдФрд░ рднрд╛рдЧред рдЗрди рдСрдкрд░реЗрд╢рдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рддреНрд░рд┐рдХреЛрдгрдорд┐рддреАрдп рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рд╕рдЯреАрдХ рдФрд░ рддреЗрдЬрд╝ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдПрдХ рддреБрдЪреНрдЫ рдХрд╛рд░реНрдп рдирд╣реАрдВ рд╣реИ рдФрд░, рдкрд╣рд┐рдпрд╛ рдХреЛ рд╕реБрджреГрдврд╝ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рддреИрдпрд╛рд░ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИред рдорд╛рд▓рд┐рдХрд╛рдирд╛
рдЗрдВрдЯреЗрд▓ рдПрдордХреЗрдПрд▓ рдХреЗ рдЕрд▓рд╛рд╡рд╛ (рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдЦрд╕реНрддрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╣реИ), рдХреЗрд╡рд▓ рддреАрди рд╡рд┐рдХрд▓реНрдк (
рдПрдХ ,
рджреЛ ,
рддреАрди ) рдереЗред
рдкрд╣рд▓рд╛ рд╡рд┐рдХрд▓реНрдк рдПрдХ рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдмрд╣реБрдд рд╣реА рдорд╛рдореВрд▓реА рдХрд╛рд░реНрдп рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╡рд╕реНрддреБрддрдГ рдХреЛрдИ рджрд╕реНрддрд╛рд╡реЗрдЬ рдпрд╛ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рджреВрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк Ccm vecmathlib рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣реИ, рдЬрд┐рд╕рдиреЗ рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдЕрдиреБрд╢рдВрд╕рд┐рдд GCC-4.7 рд╕рдВрдХрд▓рдХ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд╛рд╡рдЬреВрдж рдореЗрд░реЗ рд▓рд┐рдП рд╕рдВрдХрд▓рди рдХрд░рдиреЗ рд╕реЗ рдЗрдирдХрд╛рд░ рдХрд░ рджрд┐рдпрд╛ рдерд╛ред рдПрдХ рдЖрд╢рд╛рдЬрдирдХ рд╡рд┐рдХрд▓реНрдк, рд▓реЗрдХрд┐рди рдЕрднреА рднреА рдХреНрд░реВрдб рд▓рдЧрддрд╛ рд╣реИред рддреАрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк - SLEEF рд▓рд╛рдЗрдмреНрд░реЗрд░реА - рдХреЛ рд╡реАрд╕реАрдореИрдерд▓реАрдм рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж рдорд┐рд▓рд╛, рдЬреЛ рдЗрд╕рдХреЗ рдХреЛрдб рдмреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдХреЛрдб рдХреА рд╕рд╛рджрдЧреА рдФрд░ рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА рдЕрдзрд┐рдХрддрд╛ рдХреЗ рдХрд╛рд░рдг рдореБрдЭреЗ рддреБрд░рдВрдд рд╡рд┐рдХрд▓реНрдк рдкрд╕рдВрдж рдЖрдпрд╛ред
рдкреНрд░реЗрд░рдгрд╛ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдкрд░реАрдХреНрд╖рдг
рдореЙрдбреНрдпреВрд▓ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдкреНрд░реЗрд░рдгрд╛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ SLEEF рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВ, рдореИрдВрдиреЗ рдорд╛рдирдХ рдЧрдгрд┐рдд рдХреЗ рд╕рд╛рде SLEEF рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рд╕реА рднрд╛рд╖рд╛ рдореЗрдВ рд╕рд╛рдЗрди рдХреА рдЧрдгрдирд╛ рдХреА рдЧрддрд┐ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рд╣рдо рдПрдХ рдмрдбрд╝реЗ рдбреЗрдЯрд╛ рдРрд░реЗ рдХреЗ рд▓рд┐рдП рдПрд▓реАрдореЗрдВрдЯ рд╡рд╛рдЗрдЬ рдЧрдгрдирд╛ рдХреА рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВред
рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, SLEEF рдореЗрдВ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рдХреЛрдИ рдкреНрд░рд▓реЗрдЦрди рдФрд░ рдЙрджрд╛рд╣рд░рдг рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХрд╛рдлреА рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд▓рд┐рдЦрд┐рдд рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рдерд╛ рдХрд┐ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВред
SLEEF рд╕реНрд░реЛрдд рдХреЛрдб рдореЗрдВ рдЪрд╛рд░ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдПрдВ рд╣реЛрддреА рд╣реИрдВ:
java
,
purec
,
simd
рдФрд░
tester
ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╡рд┐рд╡рд░рдг рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рдореЗрдХрдлрд╛рдЗрд▓ рдХреЗ рд╕рд╛рде рдПрдХ README рдлрд╛рдЗрд▓ рд╣реИ рдЬреЛ рдЙрдкрд░реЛрдХреНрдд рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рд╕реЗ рдореЗрдХрдлрд╛рдЗрд▓ рдХреЛ рдЦреАрдВрдЪрддреА рд╣реИред рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рдореИрдВ
simd
рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдкреА рд░рдЦрддрд╛ рдерд╛, рдЬреЛ рдХрд┐ рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдирд╛рдо рд╕реЗ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рдореЗрдВ SIMD рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдиреБрдХреВрд▓рд┐рдд рдлрд╝рдВрдХреНрд╢рди рд╢рд╛рдорд┐рд▓ рдереЗред
simd
рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ
simd
,
simd
рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ SIMD рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ 4 рд╡реЗрд░рд┐рдПрдВрдЯ рд╕рдорд░реНрдерд┐рдд рд╣реИрдВ:
SSE2 ,
AVX ,
AVX2 рдФрд░
FMA4 ред рдлрд╝рдВрдХреНрд╢рди рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдлрд╝рд╛рдЗрд▓
sleefsimd.h
рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдП рдЧрдП рд╣реИрдВ, рдФрд░ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдЖрд╡рд╢реНрдпрдХ рд╕реЗрдЯ рдХреЛ рдЭрдВрдбреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдХрд▓рди рдореЗрдВ рдЪреБрдирд╛ рдЧрдпрд╛ рд╣реИ
-DENABLE_SSE2
,
-DENABLE_AVX
,
-DENABLE_AVX2
рдпрд╛
-DENABLE_FMA4
ред
iutsse2
рдкреНрд░рддреНрдпреЗрдХ рдирд┐рд░реНрджреЗрд╢ рд╕реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдирд┐рд╖реНрдкрд╛рджрдирдпреЛрдЧреНрдп рдПрдХрддреНрд░ рдХрд░рддрд╛ рд╣реИ:
iutsse2
,
iutavx
,
iutavx2
рдпрд╛
iutfma4
ред рдЗрди рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рдЯреЗрд╕реНрдЯрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдо (
tester
рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рд╕реЗ) рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЯреЗрд╕реНрдЯрд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрдорд╛рдВрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЖрджреЗрд╢реЛрдВ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
iut.c
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╣реИ, рдЬрд╣рд╛рдВ рд╕реЗ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
SLEEF рд╕реНрд░реЛрдд рдХреЛрдб рдореЗрдВ simd / iut.c рдлрд╝рд╛рдЗрд▓ рд╕реЗ рд╕рд╛рдЗрди рдЯреЗрд╕реНрдЯ рдлрд╝рдВрдХреНрд╢рди double xxsin(double d) { double s[VECTLENDP]; int i; for(i=0;i<VECTLENDP;i++) { s[i] = random()/(double)RAND_MAX*20000-10000; } int idx = random() & (VECTLENDP-1); s[idx] = d; vdouble a = vloadu(s); a = xsin(a); vstoreu(s, a); return s[idx]; }
рджреЛрд╣рд░реА рд╕рдЯреАрдХ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд▓рдВрдмрд╛рдИ рдХреА рдПрдХ рд╕рд░рдгреА рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛
VECTLENDP
, рдЙрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рддрд░реНрдХреЛрдВ рдХреЛ рднрд░реЗрдВ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рдФрд░ рдЗрд╕реЗ
vloadu
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд╛рд╕ рдХрд░реЗрдВ, рдЬреЛ рдЙрдиреНрд╣реЗрдВ рдЙрд╕ рд╕реНрдерд╛рди рдкрд░ рдХреЙрдкреА рдХрд░реЗрдЧрд╛ рдЬрд╣рд╛рдВ рдЖрдкрдХреЛ SIMD рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдФрд░ рдкреНрд░рдХрд╛рд░
vdouble
рдХрд╛ рдорд╛рди рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдо
vdouble
рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ
xsin
рдорд╛рди рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдПрдХ рдмрд╛рд░ рдореЗрдВ рд╕рднреА
VECLENDP
рддрд░реНрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╛рдЗрди рдорд╛рди рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рд╕реЗ
vdouble
рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред рдкрд░рд┐рдгрд╛рдо
vstoreu
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ
double
рд╕реЗ рд╕рд░рдгреА рдореЗрдВ
vstoreu
рд╣реИред
рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЕрдкрдиреА рдорд╢реАрди рдкрд░ SLEEF рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдореИрдВ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд╛ рдкреВрд░рд╛ рд╕реНрд░реЛрдд рдХреЛрдб рджреЗрддрд╛ рд╣реВрдВ рдЬреЛ рдореИрдВрдиреЗ SLEEF рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ SIMD рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рд╕рдВрднрд╛рд╡рд┐рдд рддреНрд╡рд░рдг рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдерд╛ред
SLEEF рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд╛рдЗрди рдЧрдгрдирд╛ рдХреА рдЧрддрд┐ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХрд╛ рдХрд╛рд░реНрдпрдХреНрд░рдо #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> #include "sleefsimd.h" #define TESTSIZE (VECTLENDP*10000000) double s[TESTSIZE]; double r1[TESTSIZE]; double r2[TESTSIZE]; #define COUNT 10 int main(int argc, char *argv[]) { int k, i; clock_t t1, t2; double time1, time2; double max, rmax; srandom(time(NULL)); for(i = 0; i < TESTSIZE; i++) { s[i] = random()/(double)RAND_MAX*20000-10000; } printf("Testing sin, %d values\n", TESTSIZE*COUNT); t1 = clock(); for(k = 0; k < COUNT; k++) { for(i = 0; i < TESTSIZE; i++) { r1[i] = sin(s[i]); } } t2 = clock(); time1 = (double)(t2 - t1)/CLOCKS_PER_SEC; printf("Finish sin, spent time = %lg sec\n\n", time1); printf("Testing xsin\n"); t1 = clock(); for(k = 0; k < COUNT; k++) { for(i = 0; i < TESTSIZE; i += VECTLENDP) { vdouble a = vloadu(s+i); a = xsin(a); vstoreu(r2+i, a); } } t2 = clock(); time2 = (double)(t2 - t1)/CLOCKS_PER_SEC; printf("Finish xsin, spent time = %lg sec\n\n", time2); printf("Speed ratio: %lf\n", time1/time2); max = r1[0] - r2[0]; rmax = (r1[0] - r2[0])/r1[0]; for(i = 0; i < TESTSIZE; i++) { double delta = (r1[i] - r2[i]); if(abs(delta) > abs(max)) max = delta; delta = (r1[i] - r2[i])/r1[i]; if(abs(delta) > abs(max)) rmax = delta; } printf("Max absolute delta: %lg, relative delta %lg\n", max, rmax); return 0; }
рдореЗрд░реЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рд╕рдорд░реНрдерд┐рдд рдХрдорд╛рдВрдб рдХрд╛ рд╕рдмрд╕реЗ рдЙрдиреНрдирдд рд╕реЗрдЯ AVX рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдпрдХреНрд░рдо (
simd/speedtest.c
рд╕реНрд░реЛрдд рдореЗрдВ
simd/speedtest.c
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ) рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛:
gcc -O3 -Wall -Wno-unused -Wno-attributes -DENABLE_AVX -mavx speedtest.c sleefsimddp.c sleefsimdsp.c -o speedtest -lm
рдореБрдЭреЗ рд▓рдЧрднрдЧ 4 рдмрд╛рд░ рддреНрд╡рд░рдг рдХреА рдЙрдореНрдореАрдж рдереА, рд▓реЗрдХрд┐рди рдкрд░рд┐рдгрд╛рдо рдореЗрд░реА рд╕рд╛рд░реА рдЙрдореНрдореАрджреЛрдВ рд╕реЗ рдЕрдзрд┐рдХ рд╣реЛ рдЧрдпрд╛:
Testing sin, 400000000 values Finish sin, spent time = 14.95 sec Testing xsin Finish xsin, spent time = 1.31 sec Speed ratio: 11.412214 Max absolute delta: 5.55112e-17, relative delta 1.58441e-16
10 рд╕реЗ рдЕрдзрд┐рдХ
рдмрд╛рд░ рддреНрд╡рд░рдг, рдПрдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЛрд░ рдкрд░
2 ┬╖ 10 -16 (
double
рд╕реНрд╡рдпрдВ рдХреА рд╕рдЯреАрдХрддрд╛ рдХреЗ рдЖрджреЗрд╢ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ) рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ рдЧрдгрдирд╛ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде! рдмреЗрд╢рдХ, рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдореЗрдВ, рддреНрд╡рд░рдг рдХрдо рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЦрд╕реНрддрд╛ рдореЙрдбреНрдпреВрд▓ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рдгрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред
рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рд╢рдмреНрдж
рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рд░реВрдк рд╕реЗ, рдбреЗрдЯрд╛ рдХреЛ рдмрд╣реБрдЖрдпрд╛рдореА рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдХрд╛рд░реНрдп рдХрд┐рд╕реА рднреА рдЖрдпрд╛рдо рдХреЗ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рддрддреНрд╡ рджреНрд╡рд╛рд░рд╛ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдХрдИ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЙрдирдХрд╛ рдЖрдпрд╛рдо рд╕рдВрдпреЛрдЧ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╡рд┐рд╢реЗрд╖ рдирд┐рдпрдореЛрдВ (рдЗрд╕реЗ
рдмреНрд░реЙрдбрдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ) рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкрд╣рд▓реЗ рдПрдХ рдЖрдпрд╛рдо рдореЗрдВ рдШрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЖрд╡рд╢реНрдпрдХ рдЧрдгрдирд╛ рдХреЛ рдореВрд▓ рд░реВрдк рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдЙрдЯрдкреБрдЯ рд╕рдмрд╕реЗ рдмрдбрд╝реЗ рдЖрдпрд╛рдореЛрдВ рдХрд╛ рдПрдХ рд╕рд░рдгреА рд╣реИред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╣реА рдРрдб рдлрдВрдХреНрд╢рди (рдЬреЛ рдХрд┐ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкреНрд░рдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ "рд╕реБрдиреНрди рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдСрдкрд░реЗрдЯрд░" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп) рдЖрдкрдХреЛ рджреЛ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдпрд╛ рдПрдХ-рдЖрдпрд╛рдореА рд╕рд░рдгрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдпрд╛ рдХрд┐рд╕реА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдПрдХ рд╕рд░рдгреА рдпрд╛ рдПрдХ-рдЖрдпрд╛рдореА рд╕рд░рдгреА рдХреЛ рджреЛ-рдЖрдпрд╛рдореА рдПрдХ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдЙрджрд╛рд╣рд░рдг >>> from numpy import array, add >>> add(1, 2) 3 >>> add(array([1,2]), array([4,5]))
рдЕрдВрдЧреНрд░реЗрдЬреА рдореЗрдВ рд╕реБрдиреНрди рдкрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рдЬрд╛рдирдХрд╛рд░реА
рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рджрд╕реНрддрд╛рд╡реЗрдЬ рдореЗрдВ , рд░реВрд╕реА рдореЗрдВ рдкрд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИ -
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдВ ред
рд╣рдо рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдФрд░ SIMD рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд╕рд╛рде рдЕрдкрдиреЗ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдореЙрдбреНрдпреВрд▓ рд▓рд┐рдЦрддреЗ рд╣реИрдВ
рдиреЗрдореНрдкреА рдФрд░ рд╕реНрдХрд┐рдкреНрдкреА рдХреЗ рдкрд╛рд╕ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдПрдкреАрдЖрдИ рдФрд░ рдЕрдЪреНрдЫрд╛ рджрд╕реНрддрд╛рд╡реЗрдЬ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЦрд╕реНрддрд╛ рдореЙрдбреНрдпреВрд▓ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдПрдХ рд╕рдВрдмрдВрдзрд┐рдд
рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рд╣реИ ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдПрдХ рд╕реА-рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рд░реЗрдЦреАрдп рдЪрдХреНрд░ рдореЗрдВ рд╕реНрдХреЗрд▓рд░ рддрд░реНрдХ рд╕реЗ рд╣рдореЗрдВ рдмреНрдпрд╛рдЬ рдХреА рдЧрдгрд┐рддреАрдп рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдореВрд▓реНрдп рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ:
рдПрдХ рдЦрд╕реНрддрд╛ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рд╕рд╛рдЗрди рдХреА рдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди static void double_xsin(char **args, npy_intp *dimensions, npy_intp* steps, void* data) { npy_intp i; npy_intp n = dimensions[0]; char *in = args[0], *out = args[1]; npy_intp in_step = steps[0], out_step = steps[1]; double tmp[VECTLENDP]; vdouble a; int slow_n = n % VECTLENDP; if(in_step != sizeof(double) || out_step != sizeof(double)) slow_n = n; for(i = 0; i < slow_n; i += VECTLENDP) { int j; for(j = 0; j < VECTLENDP && i + j < slow_n; j++) { tmp[j] = *(double *)in; in += in_step; } a = vloadu(tmp); a = xsin(a); vstoreu(tmp, a); for(j = 0; j < VECTLENDP && i + j < slow_n; j++) { *(double *)out = tmp[j]; out += out_step; } } if(n > slow_n) { double *in_array = (double *)in; double *out_array = (double *)out; for(i = 0; i < n - slow_n; i += VECTLENDP) { a = vloadu(in_array + i); a = xsin(a); vstoreu(out_array + i, a); } } }
рдЗрдирдкреБрдЯреНрд╕ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд▓рд┐рдП рдкреЙрдЗрдВрдЯрд░реНрд╕ рдЕрд░рдкреА рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЖрд░реНрдЧреНрд╕ рдРрд░реЗ рдореЗрдВ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдПрдХ рдЗрдирдкреБрдЯ рдФрд░ рдПрдХ рдЖрдЙрдЯрдкреБрдЯ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрдирдкреБрдЯ рдХрд╛ рдкрддрд╛
args[0]
, рдФрд░ рдЖрдЙрдЯрдкреБрдЯ
args[1]
ред рддрддреНрд╡реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛
dimensions[0]
рдХреЛ рдкрд╛рд░рд┐рдд рдХреА рдЬрд╛рддреА
dimensions[0]
ред рдЗрдирдкреБрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкреЙрдЗрдВрдЯрд░ рдХреЛ
steps[0]
рдмрдврд╝рд╛рдирд╛ рд╣реЛрдЧрд╛
steps[0]
, рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдкрд░,
steps[1]
(рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдкреЙрдЗрдВрдЯрд░ рдЯрд╛рдЗрдк
char
, рдХреНрдпреЛрдВрдХрд┐
steps
рдореЗрдВ рдмрд╛рдЗрдЯреНрд╕ рдореЗрдВ рдорд╛рди рд╣реЛрддреЗ рд╣реИрдВ)ред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдореИрдВ рдЦрд╕реНрддрд╛рд╣рд╛рд▓ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдореЗрдВ рдмрдпрд╛рди рдирд╣реАрдВ рдкрд╛ рд╕рдХрд╛ рдХрд┐
steps
рдореЗрдВ рдорд╛рди рд╕рдВрдЧрдд рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдЖрдХрд╛рд░ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдПрдХ рдкреНрд░рдпреЛрдЧ рд╕реЗ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдореЗрд░реЗ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рдиреЙрдирдЬрд╝рд░реЛ рдЖрдпрд╛рдо рдХреЗ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рдирд┐рдпрдо рд╣реИред рдЗрд╕рдХреЗ рдЙрд▓реНрд▓рдВрдШрди рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЧрдгрдирд╛ рдзреАрдореА рд╣реЛ рдЬрд╛рдПрдЧреА, рдХреНрдпреЛрдВрдХрд┐
tmp
рд╕рд░рдгреА рд╕реЗ рддрддреНрд╡реЛрдВ рдХреА рдЕрддрд┐рд░рд┐рдХреНрдд рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реИред
рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдореЗрдВ рдПрдХ рд╣реА рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рд╡рд┐рднрд┐рдиреНрди рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдкреНрд░рддреНрдпреЗрдХ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рд╕реА-рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИред рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддреЗ рд╕рдордп, рд╣рдо рд╕рдорд░реНрдерд┐рдд рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрдирдкреБрдЯ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрдпреЛрдЬрди рдХреЗ рд▓рд┐рдП рд╣рдо рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдПрдХ рд╕реА-рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдЗрд╕ рд╕рдВрдпреЛрдЬрди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдЧрд╛:
static PyUFuncGenericFunction funcs[] = {&double_xsin}; static char types[] = {NPY_DOUBLE, NPY_DOUBLE}; static void *data[] = {NULL};
types
рд╕рд░рдгреА рдореЗрдВ рдЗрдирдкреБрдЯ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рд╣реЛрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрд╣
funcs
рдФрд░
data
рд╕рд░рдгрд┐рдпреЛрдВ рд╕реЗ рдЕрдзрд┐рдХ рд▓рдВрдмрд╛ рд╣реИред
data
рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреА рдПрдХ рд╕рд░рдгреА рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрдпреЛрдЬрди рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ, рдЬрд┐рд╕реЗ рдЕрдВрддрд┐рдо рддрд░реНрдХ
void* data
рд░реВрдк рдореЗрдВ рд╕реА-рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХрд▓ рд╕реА-рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд┐рднрд┐рдиреНрди рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рд╣рдорд╛рд░реЗ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ
PyUFunc_FromFuncAndData
рдкрд░ рдХреЙрд▓
PyUFunc_FromFuncAndData
рдФрд░ рдЗрд╕рдХреЗ рдКрдкрд░ рджрд┐рдП рдЧрдП рд╕рд░рдгрд┐рдпреЛрдВ рдХреЛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (
funcs
,
data
рдФрд░
types
), рд╕рд╛рде рд╣реА рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЗрдирдкреБрдЯ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рддрд░реНрдХреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛, рд╕рдорд░реНрдерд┐рдд рдкреНрд░рдХрд╛рд░ рд╕рдВрдпреЛрдЬрдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛, рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд╛рдо рдФрд░ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд▓рд╛рдЗрдиред
рдкреВрд░реНрдг рдореЙрдбреНрдпреВрд▓ рд╕реНрд░реЛрдд рдХреЛрдб #include "Python.h" #include "numpy/ndarraytypes.h" #include "numpy/ufuncobject.h" #include "numpy/npy_3kcompat.h" #include "sleef/sleefsimd.h" static void double_xsin(char **args, npy_intp *dimensions, npy_intp* steps, void* data) { npy_intp i; npy_intp n = dimensions[0]; char *in = args[0], *out = args[1]; npy_intp in_step = steps[0], out_step = steps[1]; double tmp[VECTLENDP]; vdouble a; int slow_n = n % VECTLENDP; if(in_step != sizeof(double) || out_step != sizeof(double)) slow_n = n; for(i = 0; i < slow_n; i += VECTLENDP) { int j; for(j = 0; j < VECTLENDP && i + j < slow_n; j++) { tmp[j] = *(double *)in; in += in_step; } a = vloadu(tmp); a = xsin(a); vstoreu(tmp, a); for(j = 0; j < VECTLENDP && i + j < slow_n; j++) { *(double *)out = tmp[j]; out += out_step; } } if(n > slow_n) { double *in_array = (double *)in; double *out_array = (double *)out; for(i = 0; i < n - slow_n; i += VECTLENDP) { a = vloadu(in_array + i); a = xsin(a); vstoreu(out_array + i, a); } } } static PyMethodDef AvxmathMethods[] = { {NULL, NULL, 0, NULL} }; static PyUFuncGenericFunction funcs[1] = {&double_xsin}; static char types[] = {NPY_DOUBLE, NPY_DOUBLE}; static void *data[] = {NULL}; void register_xsin(PyObject *module) { PyObject *xsin, *d; import_array(); import_umath(); xsin = PyUFunc_FromFuncAndData(funcs, data, types, 1, 1, 1, PyUFunc_None, "sin", "AVX-accelerated sine calculation", 0); d = PyModule_GetDict(module); PyDict_SetItemString(d, "sin", xsin); Py_DECREF(xsin); } #if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "avxmath", NULL, -1, AvxmathMethods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit_avxmath(void) { PyObject *m; m = PyModule_Create(&moduledef); if (!m) { return NULL; } register_xsin(m); return m; } #else PyMODINIT_FUNC initavxmath(void) { PyObject *m; m = Py_InitModule("avxmath", AvxmathMethods); if (m == NULL) { return; } register_xsin(m); } #endif
рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ
рдкреНрд░рд▓реЗрдЦрди рд╕реЗ рдорд╛рдирдХ
setup.py
рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдореЙрдбреНрдпреВрд▓ рдирд╛рдо рдХреА рдЬрдЧрд╣ рдФрд░ SLEEF рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реА-рдлрд╛рдЗрд▓реНрд╕, рдХрдВрдкрд╛рдЗрд▓рд░ рдФрд░ рд▓рд┐рдВрдХрд░ рдЭрдВрдбреЗ рдХреЛ рдЬреЛрдбрд╝рдирд╛ред рдореИрдВрдиреЗ
avxmath.c
рдирд╛рдо рдХреА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ
avxmath.c
рдЖрдЧреЗ рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рд╕рд╣реЗрдЬрд╛,
simd
рд╕реНрд░реЛрдд рдХреЛрдб рд╕реЗ
sleef
рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХрд╛ рдирд╛рдо рдмрджрд▓рдХрд░
sleef
рджрд┐рдпрд╛ рдФрд░ рд╕рд╛рде рд╣реА рдЗрд╕реЗ
setup.py
рдмрдЧрд▓ рдореЗрдВ рд░рдЦ рджрд┐рдпрд╛ред
Avxmath рдореЙрдбреНрдпреВрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП Setup.py рдлрд╝рд╛рдЗрд▓ def configuration(parent_package='', top_path=None): import numpy from numpy.distutils.misc_util import Configuration config = Configuration('', parent_package, top_path) config.add_extension('avxmath', ['avxmath.c', 'sleef/sleefsimddp.c', 'sleef/sleefsimdsp.c'], extra_compile_args=['-O3', '-Wall', '-Wno-unused', '-Wno-attributes', '-DENABLE_AVX','-mavx'], extra_link_args=['-lm']) return config if __name__ == "__main__": from numpy.distutils.core import setup setup(configuration=configuration)
рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдП рдмрд┐рдирд╛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ
python setup.py build_ext --inplace
рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк
avxmath.so
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рддреИрдпрд╛рд░ рдореЙрдбреНрдпреВрд▓ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЕрдм рдЖрдк рд╣рдорд╛рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЕрдЬрдЧрд░ рдХреЛ рдЙрд╕реА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдЪрд▓рд╛рдПрдВ рдЬреИрд╕реЗ
avxmath.so
рдлрд╝рд╛рдЗрд▓, рдФрд░ рдЬрд╛рдВрдЪреЗрдВ:
>>> from numpy import array, pi >>> import avxmath >>> avxmath.sin(0) 0.0 >>> avxmath.sin(pi) 1.2246467991473532e-16 >>> avxmath.sin([0, pi/2, pi, 3*pi/2, 2*pi]) array([ 0.00000000e+00, 1.00000000e+00, 1.22464680e-16, -1.00000000e+00, -2.44929360e-16]) >>>
рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдХрд┐
avxmath
рдореЙрдбреНрдпреВрд▓ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд┐рдирд╛ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ, рдЖрдк рдирдП рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдФрд░ рд╕рдЯреАрдХрддрд╛ рдХрд╛ рдПрдХ рдЫреЛрдЯрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдПрд╡рдХреНрд╕рдореИрде рдореЙрдбреНрдпреВрд▓ рдХреЗ рдкрд╛рдк рдлрд╝рдВрдХреНрд╢рди рдФрд░ рдЗрд╕рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдпрдХреНрд░рдо import numpy import avxmath import time from numpy import random, pi COUNT=10 x = 2e4*random.random(40000000) - 1e4 t = time.clock() for i in xrange(COUNT): y1 = numpy.sin(x) duration1 = time.clock() - t print "numpy.sin %f sec" % duration1 t = time.clock() for i in xrange(COUNT): y2 = avxmath.sin(x) duration2 = time.clock() - t print "avxmath.sin %f sec" % duration2 delta = y2 - y1 rdelta = delta/y1 print "max absolute difference is %lg, relative %lg" % ( delta[abs(delta).argmax()], rdelta[abs(rdelta).argmax()]) print "speedup is %lg" % (duration1/duration2)
numpy.sin 15.510000 sec avxmath.sin 2.260000 sec max absolute difference is 2.22045e-16, relative 2.63873e-16 speedup is 6.86283
рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рдЧрдгрдирд╛ рдХреА рд╕рдЯреАрдХрддрд╛ рдХреЗ рд╕рд╛рде
6 рдЧреБрдирд╛ рд╕реЗ рдЕрдзрд┐рдХ рдХрд╛ рддреНрд╡рд░рдг рдорд┐рд▓рд╛, рдЬреЛ
3 ┬╖ 10 -16 рд╕реЗ рднреА рдмрджрддрд░ рдирд╣реАрдВ рдерд╛! рдореЗрдореЛрд░реА рдХреА рдПрдХ рд╕рд░рд▓ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдХреЗ рд╕рд╛рде
xsin
рдлрд╝рдВрдХреНрд╢рди
xsin
рдХреЛ
xsin
рдХрд░рдирд╛, рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ рдХрд┐ 10 рдмрд╛рд░ рдХрд╛ рддреНрд╡рд░рдг рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рдерд╛ рдХрд┐ рд╣рдореЗрдВ рдкреНрд░рд╛рдкреНрдд 2.26 рд╕реЗрдХрдВрдб рдореЗрдВ рд╕реЗ рд▓рдЧрднрдЧ 1 рд╕реЗрдХрдВрдб рдУрд╡рд░рд╣реЗрдб рдкрд░ рдЦрд░реНрдЪ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЗрд╕реА рдкреНрд░рдХрд╛рд░,
xsin
рдлрд╝рдВрдХреНрд╢рди рдХреЛ
math.h
рд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд╕рд╛рдЗрди рдХреЗ
xsin
рдмрджрд▓рдиреЗ рдкрд░, рд╣рдо рдкрд╛рддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ
avxmath.sin
рдФрд░
numpy.sin
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЧрдгрдирд╛ рд╕рдордп рдЙрдЪреНрдЪ рд╕рдЯреАрдХрддрд╛ рдХреЗ рд╕рд╛рде рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред
рдЗрд╕ рдкреНрд░рдХрд╛рд░, SIMD рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЖрдк рд╕рд╛рдзрд╛рд░рдг рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЖрдпрд╛рдд рдХреЛ рд╕реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд▓реЛрдЧреЛрдВ рдХреЗ рд╕реНрдерд╛рди рдкрд░ рдмрджрд▓рдХрд░, рдЦрд╕рдЦрд╕ тАЛтАЛрдФрд░ рдЫреАрдВрдЯреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреА рдЧрдИ рдЧрдгрдирд╛рдУрдВ рдореЗрдВ рдХрд╛рдлреА рддреЗрдЬреА рд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред рдФрд░ рд╣рд╛рдВ, рдЗрд╕ рд▓реЗрдЦ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХреБрдЫ рдЙрдиреНрдирдд рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб
avxmath
рдореЙрдбреНрдпреВрд▓
рд╕рдВрджрд░реНрдн рджреНрд╡рд╛рд░рд╛
avxmath
рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред
рдЕрдкрдбреЗрдЯ : 1e10 рдпрд╛ рдЕрдзрд┐рдХ рдХреЗ рдЖрджреЗрд╢ рдХреЗ рддрд░реНрдХ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП SLEEF рдХреА рд╕рд╛рдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░реЗрдВ (
рдЯрд┐рдкреНрдкрдгреА рджреЗрдЦреЗрдВ)