【发布时间】:2014-06-05 16:10:58
【问题描述】:
我正在做一个矩阵乘法的项目。我已经能够编写 C 代码,并且能够使用 Microsoft Visual Studio 2012 编译器为其生成汇编代码。编译器生成的代码如下所示。编译器使用了 SSE 寄存器,这正是我想要的,但它不是最好的代码。我想优化此代码并将其与 C 代码内联编写,但我不理解汇编代码。基本上汇编代码只适用于矩阵的一维,下面的代码只适用于 4 x 4 矩阵。我怎样才能使它适合 n*n 矩阵大小。
C++代码如下:
#define MAX_NUM 10
#define MAX_DIM 4
int main () {
float mat_a [] = {1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0};
float mat_b [] = {1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0};
float result [] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
int num_row = 4;
int num_col = 4;
float sum;
for (int i = 0; i < num_row; i++) {
for (int j = 0; j < num_col; j++) {
sum = 0.0;
for (int k = 0; k < num_row; k++) {
sum = sum + mat_a[i * num_col + k] * mat_b[k * num_col + j];
}
*(result + i * num_col + j) = sum;
}
}
return 0;
}
汇编代码如下:
; Listing generated by Microsoft (R) Optimizing Compiler Version 17.00.50727.1
TITLE C:\Users\GS\Documents\Visual Studio 2012\Projects\Assembly_InLine\Assembly_InLine\Source.cpp
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES
PUBLIC _main
PUBLIC __real@00000000
PUBLIC __real@3f800000
PUBLIC __real@40000000
PUBLIC __real@40400000
PUBLIC __real@40800000
EXTRN @_RTC_CheckStackVars@8:PROC
EXTRN @__security_check_cookie@4:PROC
EXTRN __RTC_InitBase:PROC
EXTRN __RTC_Shutdown:PROC
EXTRN ___security_cookie:DWORD
EXTRN __fltused:DWORD
; COMDAT __real@40800000
CONST SEGMENT
__real@40800000 DD 040800000r ; 4
CONST ENDS
; COMDAT __real@40400000
CONST SEGMENT
__real@40400000 DD 040400000r ; 3
CONST ENDS
; COMDAT __real@40000000
CONST SEGMENT
__real@40000000 DD 040000000r ; 2
CONST ENDS
; COMDAT __real@3f800000
CONST SEGMENT
__real@3f800000 DD 03f800000r ; 1
CONST ENDS
; COMDAT __real@00000000
CONST SEGMENT
__real@00000000 DD 000000000r ; 0
CONST ENDS
; COMDAT rtc$TMZ
rtc$TMZ SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ ENDS
; COMDAT rtc$IMZ
rtc$IMZ SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
rtc$IMZ ENDS
; Function compile flags: /Odtp /RTCsu /ZI
; COMDAT _main
_TEXT SEGMENT
_k$1 = -288 ; size = 4
_j$2 = -276 ; size = 4
_i$3 = -264 ; size = 4
_sum$ = -252 ; size = 4
_num_col$ = -240 ; size = 4
_num_row$ = -228 ; size = 4
_result$ = -216 ; size = 64
_mat_b$ = -144 ; size = 64
_mat_a$ = -72 ; size = 64
__$ArrayPad$ = -4 ; size = 4
_main PROC ; COMDAT
; File c:\users\gs\documents\visual studio 2012\projects\assembly_inline\assembly_inline\source.cpp
; Line 4
push ebp
mov ebp, esp
sub esp, 484 ; 000001e4H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-484]
mov ecx, 121 ; 00000079H
mov eax, -858993460 ; ccccccccH
rep stosd
mov eax, DWORD PTR ___security_cookie
xor eax, ebp
mov DWORD PTR __$ArrayPad$[ebp], eax
; Line 5
movss xmm0, DWORD PTR __real@3f800000
movss DWORD PTR _mat_a$[ebp], xmm0
movss xmm0, DWORD PTR __real@40000000
movss DWORD PTR _mat_a$[ebp+4], xmm0
movss xmm0, DWORD PTR __real@40400000
movss DWORD PTR _mat_a$[ebp+8], xmm0
movss xmm0, DWORD PTR __real@40800000
movss DWORD PTR _mat_a$[ebp+12], xmm0
movss xmm0, DWORD PTR __real@3f800000
movss DWORD PTR _mat_a$[ebp+16], xmm0
movss xmm0, DWORD PTR __real@40000000
movss DWORD PTR _mat_a$[ebp+20], xmm0
movss xmm0, DWORD PTR __real@40400000
movss DWORD PTR _mat_a$[ebp+24], xmm0
movss xmm0, DWORD PTR __real@40800000
movss DWORD PTR _mat_a$[ebp+28], xmm0
movss xmm0, DWORD PTR __real@3f800000
movss DWORD PTR _mat_a$[ebp+32], xmm0
movss xmm0, DWORD PTR __real@40000000
movss DWORD PTR _mat_a$[ebp+36], xmm0
movss xmm0, DWORD PTR __real@40400000
movss DWORD PTR _mat_a$[ebp+40], xmm0
movss xmm0, DWORD PTR __real@40800000
movss DWORD PTR _mat_a$[ebp+44], xmm0
movss xmm0, DWORD PTR __real@3f800000
movss DWORD PTR _mat_a$[ebp+48], xmm0
movss xmm0, DWORD PTR __real@40000000
movss DWORD PTR _mat_a$[ebp+52], xmm0
movss xmm0, DWORD PTR __real@40400000
movss DWORD PTR _mat_a$[ebp+56], xmm0
movss xmm0, DWORD PTR __real@40800000
movss DWORD PTR _mat_a$[ebp+60], xmm0
; Line 6
movss xmm0, DWORD PTR __real@3f800000
movss DWORD PTR _mat_b$[ebp], xmm0
movss xmm0, DWORD PTR __real@40000000
movss DWORD PTR _mat_b$[ebp+4], xmm0
movss xmm0, DWORD PTR __real@40400000
movss DWORD PTR _mat_b$[ebp+8], xmm0
movss xmm0, DWORD PTR __real@40800000
movss DWORD PTR _mat_b$[ebp+12], xmm0
movss xmm0, DWORD PTR __real@3f800000
movss DWORD PTR _mat_b$[ebp+16], xmm0
movss xmm0, DWORD PTR __real@40000000
movss DWORD PTR _mat_b$[ebp+20], xmm0
movss xmm0, DWORD PTR __real@40400000
movss DWORD PTR _mat_b$[ebp+24], xmm0
movss xmm0, DWORD PTR __real@40800000
movss DWORD PTR _mat_b$[ebp+28], xmm0
movss xmm0, DWORD PTR __real@3f800000
movss DWORD PTR _mat_b$[ebp+32], xmm0
movss xmm0, DWORD PTR __real@40000000
movss DWORD PTR _mat_b$[ebp+36], xmm0
movss xmm0, DWORD PTR __real@40400000
movss DWORD PTR _mat_b$[ebp+40], xmm0
movss xmm0, DWORD PTR __real@40800000
movss DWORD PTR _mat_b$[ebp+44], xmm0
movss xmm0, DWORD PTR __real@3f800000
movss DWORD PTR _mat_b$[ebp+48], xmm0
movss xmm0, DWORD PTR __real@40000000
movss DWORD PTR _mat_b$[ebp+52], xmm0
movss xmm0, DWORD PTR __real@40400000
movss DWORD PTR _mat_b$[ebp+56], xmm0
movss xmm0, DWORD PTR __real@40800000
movss DWORD PTR _mat_b$[ebp+60], xmm0
; Line 7
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+4], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+8], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+12], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+16], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+20], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+24], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+28], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+32], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+36], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+40], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+44], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+48], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+52], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+56], xmm0
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _result$[ebp+60], xmm0
; Line 9
mov DWORD PTR _num_row$[ebp], 4
; Line 10
mov DWORD PTR _num_col$[ebp], 4
; Line 14
mov DWORD PTR _i$3[ebp], 0
jmp SHORT $LN9@main
$LN8@main:
mov eax, DWORD PTR _i$3[ebp]
add eax, 1
mov DWORD PTR _i$3[ebp], eax
$LN9@main:
mov eax, DWORD PTR _i$3[ebp]
cmp eax, DWORD PTR _num_row$[ebp]
jge $LN7@main
; Line 15
mov DWORD PTR _j$2[ebp], 0
jmp SHORT $LN6@main
$LN5@main:
mov eax, DWORD PTR _j$2[ebp]
add eax, 1
mov DWORD PTR _j$2[ebp], eax
$LN6@main:
mov eax, DWORD PTR _j$2[ebp]
cmp eax, DWORD PTR _num_col$[ebp]
jge $LN4@main
; Line 16
movss xmm0, DWORD PTR __real@00000000
movss DWORD PTR _sum$[ebp], xmm0
; Line 17
mov DWORD PTR _k$1[ebp], 0
jmp SHORT $LN3@main
$LN2@main:
mov eax, DWORD PTR _k$1[ebp]
add eax, 1
mov DWORD PTR _k$1[ebp], eax
$LN3@main:
mov eax, DWORD PTR _k$1[ebp]
cmp eax, DWORD PTR _num_row$[ebp]
jge SHORT $LN1@main
; Line 18
mov eax, DWORD PTR _i$3[ebp]
imul eax, DWORD PTR _num_col$[ebp]
add eax, DWORD PTR _k$1[ebp]
mov ecx, DWORD PTR _k$1[ebp]
imul ecx, DWORD PTR _num_col$[ebp]
add ecx, DWORD PTR _j$2[ebp]
movss xmm0, DWORD PTR _mat_a$[ebp+eax*4]
mulss xmm0, DWORD PTR _mat_b$[ebp+ecx*4]
addss xmm0, DWORD PTR _sum$[ebp]
movss DWORD PTR _sum$[ebp], xmm0
; Line 19
jmp SHORT $LN2@main
$LN1@main:
; Line 20
mov eax, DWORD PTR _i$3[ebp]
imul eax, DWORD PTR _num_col$[ebp]
lea ecx, DWORD PTR _result$[ebp+eax*4]
mov edx, DWORD PTR _j$2[ebp]
movss xmm0, DWORD PTR _sum$[ebp]
movss DWORD PTR [ecx+edx*4], xmm0
; Line 21
jmp $LN5@main
$LN4@main:
; Line 22
jmp $LN8@main
$LN7@main:
; Line 24
xor eax, eax
; Line 25
push edx
mov ecx, ebp
push eax
lea edx, DWORD PTR $LN16@main
call @_RTC_CheckStackVars@8
pop eax
pop edx
pop edi
pop esi
pop ebx
mov ecx, DWORD PTR __$ArrayPad$[ebp]
xor ecx, ebp
call @__security_check_cookie@4
mov esp, ebp
pop ebp
ret 0
npad 1
$LN16@main:
DD 3
DD $LN15@main
$LN15@main:
DD -72 ; ffffffb8H
DD 64 ; 00000040H
DD $LN12@main
DD -144 ; ffffff70H
DD 64 ; 00000040H
DD $LN13@main
DD -216 ; ffffff28H
DD 64 ; 00000040H
DD $LN14@main
$LN14@main:
DB 114 ; 00000072H
DB 101 ; 00000065H
DB 115 ; 00000073H
DB 117 ; 00000075H
DB 108 ; 0000006cH
DB 116 ; 00000074H
DB 0
$LN13@main:
DB 109 ; 0000006dH
DB 97 ; 00000061H
DB 116 ; 00000074H
DB 95 ; 0000005fH
DB 98 ; 00000062H
DB 0
$LN12@main:
DB 109 ; 0000006dH
DB 97 ; 00000061H
DB 116 ; 00000074H
DB 95 ; 0000005fH
DB 97 ; 00000061H
DB 0
_main ENDP
_TEXT ENDS
END
【问题讨论】:
-
如果是C代码,为什么是C++标签而不是C?
-
这不是最好的代码你确定吗?如今,要智胜编译器/编译器编写者并不容易。通常他们比你更了解这个主题,尤其是。当涉及流水线等时。您是否使用了正确的编译器标志?
-
C++ 是从 C 派生的。我正在用 C++ 编写这段代码。这是 .cpp 文件。
-
“我不懂汇编代码”...“它不是最好的代码”...我不明白你怎么能认为它不是最好的代码,如果你甚至不明白...您能够比您的编译器更好地手动优化代码的机会可能没有您想象的那么高...
-
发布的程序集看起来像一个 Debug 构建。尝试查看优化的 Release 构建的输出。
标签: c++ c visual-studio-2012 optimization assembly