窗户多线程输入它们的功能,但随机返回结果(Windows multicore threads ent

2019-10-31 09:03发布

一连几天我有麻烦了Windows 7 Ivy Bridge的系统上创建四个线程(四个核心)。 我已经创造了NASM一个简单的测试功能,如最小的,因为它可以,向人们展示。

该计划增加从0到1十亿计数器并返回结果。 多核处理,我分割它,以便芯1从0计数到250万,芯2的计数为2.5万〜500万,等

出于测试目的。 程序返回与来自每个核心的三个值的12元件阵列。 元素1-4是由CreateThread的返回线程处理; 元件5-8是线程进入测试功能(Test_fn)后,从呼叫的返回值GetCurrentThreadId; 和元件9-12是由每个线程执行的计算的结果(从startbyte计数到endbyte)。

数组返回(TestInfo)显示的CreateThread总是成功,因为前四个元素,总是包含由CreateThread的返回线程句柄(在我的测试),和元素5-8总是在进入功能Test_fn从GetCurrentThreadId返回一个值。 的问题是,元件9-12(来自每个核心的计算结果)并不总是从数学运算中Test_fn的主体返回一个值,和分布是随机的(有时芯1和4会成功,有时芯2和3只,等等)。 这意味着线程并不总是成功运行,分配给他们的计算,即使他们创建和调用Test_fn。

这是一个从Python中调用的DLL,但它可以从C或C ++调用。 它不带任何参数,并且它返回一个指针到12元件阵列测试TestInfo(如上所述)。 入口点是Main_Entry_fn,这就要求Init_Cores_fn。 线程是指出Test_fn。

所以我的问题是,为什么在线程并不总是可靠地返回从Test_fn一个值,即使线程明确要求Test_fn。

; Header Section
[BITS 64]
[default rel]

extern malloc, calloc, realloc, free
global Main_Entry_fn
export Main_Entry_fn
extern CreateThread, CloseHandle, ExitThread
extern WaitForMultipleObjects, GetCurrentThreadId

section .data align=16
const_1000000000: dq 1000000000
ThreadID:  dq 0
TestInfo: times 12 dq 0
ThreadInfo: times 3 dq 0
ThreadInfo2: times 3 dq 0
ThreadInfo3: times 3 dq 0
ThreadInfo4: times 3 dq 0
ThreadHandles: times 4 dq 0
Division_Size: dq 0
Start_Byte: dq 0
End_Byte: dq 0
Return_Data_Array: times 4 dq 0
Core_Number: dq 0

section .text

; ______________________________________

Init_Cores_fn:

; Calculate the data divisions
mov rax,[const_1000000000]
mov rbx,4 ;cores
xor rdx,rdx
div rbx
mov [End_Byte],rax
mov [Division_Size],rax
mov rax,0
mov [Start_Byte],rax

; Populate the ThreadInfo arrays to pass for each core
; ThreadInfo:  (1) startbyte; (2) endbyte; (3) Core_Number (0, 8, 16, 24)
mov rdi,ThreadInfo
mov rax,[Start_Byte]
mov [rdi],rax
mov rax,[End_Byte]
mov [rdi+8],rax
mov rax,[Core_Number]
mov [rdi+16],rax

call DupThreadInfo ; Create ThreadInfo arrays for cores 2-4

mov rbp,rsp ; preserve caller's stack frame
sub rsp,56 ; Shadow space (was 32)

; _____

label_0:

mov rax,[Core_Number]
cmp rax,0
jne sb2
mov rdi,ThreadInfo
jmp sb5
sb2:cmp rax,8
jne sb3
mov rdi,ThreadInfo2
jmp sb5
sb3:cmp rax,16
jne sb4
mov rdi,ThreadInfo3
jmp sb5
sb4:cmp rax,24
jne sb5
mov rdi,ThreadInfo4
sb5:

; _____
; Create Threads

mov rcx,0               ; lpThreadAttributes (Security Attributes)
mov rdx,0               ; dwStackSize
mov r8,Test_fn          ; lpStartAddress (function pointer)
mov r9,rdi              ; lpParameter (array of data passed to each core)
mov rax,0
mov [rsp+32],rax            ; use default creation flags
mov rdi,ThreadID
mov [rsp+40],rdi            ; ThreadID

call CreateThread

; Move the handle into ThreadHandles array (returned in rax)
mov rdi,ThreadHandles
mov rcx,[Core_Number]
mov [rdi+rcx],rax
mov rdi,TestInfo
mov [rdi+rcx],rax

mov rax,[Core_Number]
add rax,8
mov [Core_Number],rax
mov rbx,32 ; Four cores
cmp rax,rbx
jl label_0

; _____
; Wait

mov rcx,4 ;rax          ; number of handles
mov rdx,ThreadHandles       ; pointer to handles array
mov r8,0                ; wait for all threads to complete
mov r9,5000         ; milliseconds to wait

call WaitForMultipleObjects

; _____

mov rsp,rbp
jmp label_900

; ______________________________________

Test_fn:

;______

; GetCurrentThreadId
mov rdi,rcx
push rcx
call GetCurrentThreadId
mov rcx,[rdi+16] ; startbyte
mov rdi,TestInfo
mov [rdi+rcx+32],rax
pop rcx

;______

mov rdi,rcx

mov r14,[rdi] ; Start_Byte
mov r15,[rdi+8] ; End_Byte
mov r13,[rdi+16] ; Core_Number

;______

label_401:
cmp r14,r15
jge label_899

; n += 1
add r14,1

jmp label_401

;______

label_899:

mov rdi,Return_Data_Array
mov [rdi+r13],r14

mov rdi,TestInfo
mov [rdi+r13+64],r14

mov rbp,ThreadHandles
mov rax,[rbp+r13]
;mov [rdi+rbx+64],rax

call ExitThread

ret

; __________

label_900:

mov rdi,ThreadHandles
mov r8,0
label_900_01:
mov rcx,[rdi+r8]
call CloseHandle
add r8,8
cmp r8,32
jl label_900_01

mov rdi,TestInfo
mov rax,rdi

ret

; __________
; Main Entry

Main_Entry_fn:
push rdi
push rbp
call Init_Cores_fn
pop rbp
pop rdi
ret

DupThreadInfo:
mov rdi,ThreadInfo2
mov rax,8
mov [rdi+16],rax ; Core Number
mov rax,[Start_Byte]
add rax,[Division_Size]
mov [rdi],rax
mov rax,[End_Byte]
add rax,[Division_Size]
mov [rdi+8],rax
mov [Start_Byte],rax

mov rdi,ThreadInfo3
mov rax,16
mov [rdi+16],rax ; Core Number
mov rax,[Start_Byte]
mov [rdi],rax
add rax,[Division_Size]
mov [rdi+8],rax
mov [Start_Byte],rax

mov rdi,ThreadInfo4
mov rax,24
mov [rdi+16],rax ; Core Number
mov rax,[Start_Byte]
mov [rdi],rax
add rax,[Division_Size]
mov [rdi+8],rax
mov [Start_Byte],rax
ret

芯使用3-元件阵列的ThreadInfo,ThreadInfo2,ThreadInfo3和ThreadInfo4用于他们的数据。 为每个线程,它们包含开始编号,结束数,并乘以8的芯数:

0 2.5亿0

2.5亿5亿8

5亿7.5亿16

7.5亿10亿24

这里有四个独立的测试结果:

1548 1716 1688六千四百六十○分之一千七百六十八6464 6468250000000分之64720 0 10亿

1744 860 1724六千七百八十○分之一千六百六十八6784 6788 6792/0 0 0 10亿

1632 1588 1488七千○二十四分之八百七十二7028 7032 7036/0 5亿0 0

1740 1732 16846876分之15366884 6888250000000分之68800 7.5亿0

前四个数字是每个核心的线程句柄; 第二四个编号是从GetCurrentThreadId在进入Test_fn返回值,并且最后一组四个数字的是在Test_fn执行的简单的计算的结果; 它们表明内核在一些但不是所有情况下返回正确的数据。

感谢您的任何想法。

文章来源: Windows multicore threads enter their function but return results randomly