找回密码
 加入
搜索
查看: 7999|回复: 10

[系统综合] [已解决] CPU 曲線圖 (畫出sin圖形)

  [复制链接]
发表于 2012-11-16 15:34:45 | 显示全部楼层 |阅读模式
本帖最后由 edisonx 于 2012-11-16 17:51 编辑

這問題是微軟(Microsoft)的面試題,在工作管理員裡之 CPU 曲線圖,顯示 sin 圖形,小弟在 C 上作業正常,執行結果如下。



由於想熟悉 AutoIt 語法,轉成 AutoIt 後圖形變了樣



細思差別有幾個可能,不確定是哪種,想徵求不同網友之意見。


(1) 我的  code 有問題?

以下會附 AU3 code,但大致上都有進行過逐步確認、除錯,有錯機會大概不大(吧?)

(2) Main 裡最後之 dead loop

在 C 裡面, Main 裡最後不用卡一個 while(1); 在 Thread 被終止前主程序都會一定在跑。
但 AU3 裡面不放 While (nothing) WEnd 的話,主程序跑完時 Thread 似乎就會自動回收、自己跳出來,
而 while(1) 裡面要 Sleep 多少這個又難算了,試過幾個可能性數值 (no-sleep、sleep(1)、sleep(slic-time) 都失敗,

(3) 語言特性?

左思右想,dead loop 原因可能是最大 (雖這也是語言特性就是了),其次是 AU3 語言特性問題。語言特性又可能是,它的計算太慢,導致推導出之方法無法使用;
又或是如官網所說的:它不支援多行緒 (multi-thread),導致連一般的 Multi-Thread API 都出了問題?

由於 C language 非本論壇主要程式語言,對 C language src 有興趣玩玩可再留言,小弟將再附件。

附上 AU3 code,如下


#include <winapi.au3>
#include <array.au3>

Main()

; -----------------------------------------------------------------------
; Constant Define

Const $COUNT = 400
Const $SPLIT     = 0.01
Const $PI            =  3.14159265358979
Const $SLOPE    = 150
Const $INTERVAL = 400

; -----------------------------------------------------------------------
; Dll Call
Func GetTickCount()
        Local $ret = DllCall("kernel32.dll","int","GetTickCount")
        return $ret[0]
EndFunc

Func CreateThread($pFunc)
        Local $ret = 10
        Local $hThreadId = DllStructCreate("DWORD")
        Local $handle = DllCallbackRegister($pFunc, "int", "ptr")
        Local $ret = DllCall("kernel32.dll","ptr","CreateThread", "ptr", 0, "dword", 0, "ptr", DllCallbackGetPtr($handle), "ptr", 0, "dword", 4, "dword*", 0)
        return $ret[6]
EndFunc

Func SetThreadAffinityMask($hThread, $iProcessor)
        Local $ret
        $ret = DllCall("kernel32.dll", "DWORD", "SetThreadAffinityMask", "HANDLE", $hThread, "DWORD*", $iProcessor)
        ; ConsoleWrite(@error  & @CRLF)
        return $ret[0]
EndFunc

Func ResumeThread($hThread)
        Local $ret = DllCall("kernel32.dll", "DWORD", "ResumeThread", "DWORD", $hThread)
        ; ConsoleWrite(@error  & @CRLF)
        return $ret[0]
EndFunc

Func GetCurrentThread()
        Local $ret = DllCall("kernel32.dll", "HANDLE", "GetCurrentThread")
        ; ConsoleWrite(@error  & @CRLF)
        return $ret[0]
EndFunc

Func SuspendThread($hThread)
        Local $ret = DllCall("kernel32.dll", "DWORD", "ResumeThread", "DWORD", $hThread)
        ; ConsoleWrite(@error  & @CRLF)
        return $ret[0]
EndFunc

; ---------------------------------------------------------------
Func SinThread($Sin)
        Local $busySpan[$COUNT]
        Local $idleSpan[$Count]
        Local $half = INT($INTERVAL / 2)
        Local $Rad = 0.0
        Local $startTime
        Local $i = 0

        For $i=0 to $COUNT-1
                $busySpan[$i] = INT($half  * (1.0  + sin($PI * $rad) ))
                 $idleSpan[$i] = INT($half  - $busySpan[$i])
                $rad += $Split
        Next

        While 1
                $i = Mod($i, $Count)
                $startTime = GetTickCount()

                while( GetTickCount() - $startTime <= $busySpan[$i])
                WEnd

                Sleep($idleSpan[$i])
                $i+=1
        WEnd
        return 0
EndFunc

; ---------------------------------------------------------------
Func SawThread($Saw)
        Local $busySpan[$COUNT]
        Local $idleSpan[$Count]
        Local $half = INT($INTERVAL / 2)
        Local $Rad = 0.0
        Local $startTime
        Local $i = 0

        For $i=0 to $COUNT-1
                $busySpan[$i] = INT($SLOPE*$Rad)
                 $idleSpan[$i] = INT($INTERVAL - $busySpan[$i])
                $rad += $Split
        Next

        While 1
                $i = Mod($i, $Count)
                $startTime = GetTickCount()

                while( GetTickCount() - $startTime <= $busySpan[$i])
                WEnd

                Sleep($idleSpan[$i])
                $i+=1
        WEnd
        return 0
EndFunc

; ---------------------------------------------------------------
; Main Function

Func Main()
        ; Dim $dwThread1, $dwThread2
        Dim $hThread1, $hThread2

        $hThread1 = CreateThread("SinThread")
        $hThread2 = CreateThread("SawThread")
        SetThreadAffinityMask($hThread1, 1)
        SetThreadAffinityMask($hThread2, 2)
        ResumeThread($hThread1)
        ResumeThread($hThread2)
        SuspendThread(GetCurrentThread())

         While 1
                ; Sleep(16) ; Slic Time Of Windows = 15.75 ms
                 ; Sleep(1) ; Slic Time Of Windows = 15.75 ms
         WEnd
        Return 0
EndFunc



以上,謝謝各位不吝賜教,小弟先行感激。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2012-11-16 17:31:41 | 显示全部楼层
回复 1# edisonx


    As for AutoIt script 'code', AutoIt only interprets this code on ONE thread. IF you know about Adlib, DLLCallback, and Keyboard/Mouse Hooking code (look around the forum for those), you'll find out soon enough that when AutoIt gets interrupted by one of those methods, it will stop interpreting the main script code (wherever it was at), and interpret from the place it was interrupted from (until it returns).  So its impossible in native script code.

    Binary code/Machine code is the only way you'll get another thread going in AU3, and that means getting your hands dirty, so you must be first step to learn assemble language .

评分

参与人数 1金钱 +20 收起 理由
edisonx + 20

查看全部评分

 楼主| 发表于 2012-11-16 17:45:12 | 显示全部楼层
回复 2# happytc


happytc 專業素養真深厚,謝謝您的解釋,我獲益良多。
小弟金錢不多,一點心意,只能給系統允許上限,還望 happytc 海涵。
发表于 2012-11-16 18:19:34 | 显示全部楼层
理论上可以实现的,我随便写了一个,画出如下图像。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×

评分

参与人数 1金钱 +20 收起 理由
edisonx + 20 這圖形跑得真漂亮

查看全部评分

 楼主| 发表于 2012-11-16 19:02:25 | 显示全部楼层
本帖最后由 edisonx 于 2012-11-16 19:49 编辑

回复 4# seeyou


可能您誤會我的原題意了,我的方法是真的用程式的技巧,
去控制「工作管理員」裡面的「CPU 效能曲線圖」,
點擊上述的大圖,也是從「工作管理員」讓它跑一分鐘,再截圖下來,
而不是去 "模擬" 畫出效能曲線圖,這兩個差別頗大。

另外我不否認,原題意在單核心 CPU 底下工作是很容易辦到的事,
但在多核心系統底下工作要辦到的話,沒有 SetThreadAffinityMask 大概是辦不到的事吧。

補一下試跑之影片  http://www.youtube.com/watch?v=UwxKI-iHGuk&feature=youtu.be
发表于 2012-11-16 20:17:25 | 显示全部楼层
回复 5# edisonx


    的确,我是在单核情况下,多核做不了。
PS:大陆是一个局域网,看不到你发的youtube,要等下周再看。
发表于 2012-11-16 20:25:48 | 显示全部楼层
回复 5# edisonx


    我上面的图片不是用gdi画的,而是用程式控制的,就如你说的是Affinity之功劳。
 楼主| 发表于 2012-11-16 21:54:49 | 显示全部楼层
回复 7# seeyou

真驚人,要跑出那麼漂亮的曲線我可要跑很久。
youtube 問題還真頭疼,(不過確認您的作法應是無誤了),
這陣子我再評估,有無大陸可看到視頻之網站好了,
謝謝您的細心回覆與測試 :)
发表于 2012-11-16 23:11:27 | 显示全部楼层
挺有意思的东东
发表于 2012-11-17 07:18:43 | 显示全部楼层
学习一下,,
发表于 2012-11-21 17:48:49 | 显示全部楼层
收藏一下,不错
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-11-18 10:45 , Processed in 0.189666 second(s), 29 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表