1. 請寫出c/c++語言實現矩陣乘法加速的常用方法
for(i=0;i
i) for(j=0;j
j){ sum=0;
for(k=0;k
但是考慮了快取記憶體的問題後,其實有一種更好的實現方式:
for(i=0;i
i) for(k=0;k{
r=a[i][k];
for(j=0;j
細看一番就會發現這兩種實現語義是等價的,但是後者的實際執行效率卻比前者高。
那為什麼會如此呢?
那是因為cpu讀資料時,並不是直接訪問記憶體,而是先檢視快取中是否有資料,有的話直接從快取讀取。而從快取讀取資料比從記憶體讀資料快很多。
當資料不在快取中時,cpu會將包含資料在內的乙個資料塊讀到快取,如果程式具有良好空間區域性性,那麼第一次cache miss後,之後的幾次資料訪問就可以直接在快取中完成。除了空間區域性性(程式傾向於引用與當前資料鄰近的資料)之外,還有時間區域性性(程式傾向於引用最近被引用過的資料)。
回到矩陣乘法。(我們只考慮內迴圈)
前者對矩陣a,有良好的空間區域性性,假設一次能快取四個元素,則每次迭代對於a只有0.25次miss,但是對於b,則不然,因此b是按列訪問的,每次訪問都會miss,因此每次迭代總的miss數是1.25。
後者對於矩陣c和矩陣b都有良好的區域性性,每次迭代都只有0.25詞miss,因此總的miss數是0.5。後者每次迭代多了一次儲存(對c[i][j]寫入),但是即便如此,後者的執行效率也比前者高。
總而言之,要想程式跑得快,就要在程式中多利用區域性性,讓快取hold住你的資料,減少訪存次數。要知道cpu可以在3個時鐘週期內訪問到l1 cache,10個時鐘週期左右的時間訪問到l2 cache。訪問記憶體卻要上百個時鐘週期,孰快孰慢,很清楚了吧?
2. 找到乙個陣列中出現頻率超過12
的數,要求時間複雜度o(
n),空間複雜度o(1)
主要想法是用乙個計數器c和乙個變數v,首先將陣列的第乙個數給變數賦值v,並給計數器+1,此後如果讀到相同的數則計數器+1,如果計數器的值小於0則將,剛讀入的數賦值給變數v,並重複操作,最後變數v的值便是陣列中頻率超過12
的數。如果題目中沒指出陣列中一定存在超過12
頻率的數的話,則再將陣列掃瞄一遍,看值等於v的元素數量是否大於陣列數量的一半。
python實現**如下:
if __name__ == '__main__':
a = [1,3,4,3,3,7,3,11,3]
count = 1
value = a[0]
for i in xrange(1,len(a)):
if a[i] == value:
count += 1
else:
count -= 1
if count < 0:
count = 1
value = a[i]
count = 0
for i in xrange(0, len(a)):
if a[i] == value:
count +=1
if count > len(a)/2:
print value
3. 找到乙個陣列中出現頻率超過13
的數,要求時間複雜度o(
n),空間複雜度o(1)
此題和上一題類似,主要思想是利用兩個計數器和兩個變數,首先先將陣列的前兩個數讀入變數,知道讀到相同的數則對應的計數器加一,否則讀到非兩個變數中的數則兩個計數器同時減去1,如果計數器的值小於0則將,剛讀入的數賦值給變數,並重複操作,最後變數中的值便是陣列中頻率超過13
的數。和上一題類似就不貼**了。
4.二分查詢,要求找到陣列中第乙個滿足要求的數
這個沒什麼好解釋的,微軟的程式設計之美上有提到,但是其中起到的第乙個改進方法即midindex = maxindex + (maxindex - minindex)/2,如果用python寫的話就不用考慮這點了,因為python隨便賦多大值都不會有越界錯誤。
def
bisearch_left
(array, target_value):
max_index = len(array) - 1
min_index = 0
while min_index < max_index-1: #當搜尋範圍只有兩個數停止
mid_index = (max_index + min_index)/2
if target_value <= array[mid_index]: #取等號保證取index較小的數
max_index = mid_index
else:
min_index = mid_index
if array[min_index] == target_value:
return min_index
elif array[max_index] == target_value:
return max_index
else:
return -1;
程式設計題彙總4
本部分主要是機器學習的題目 1.神經網路訓練時使用dropout主要目的是什麼?訓練和測試時使用的區別是什麼 2.深度學習解決過擬合和欠擬合的策略都有哪些?過擬合 data augmentation。人工增加訓練集的大小.通過平移,翻轉,加雜訊等方法從已有資料中創造出一批 新 的資料.regular...
Python刷題彙總3
利用map和reduce編寫乙個str2float函式,把字串 123.456 轉換成浮點數123.456 from functools import reduce 123.456 digits defstr2float s defchar2num s return digits s n s.ind...
筆試程式設計題彙總 2
描述 給乙個整數陣列num,和乙個鎮整數k,能否把陣列num切成k個子集,且各個子集的和相等,返回布林型別 輸入輸出 輸入 乙個整數陣列num和乙個正整數k 輸出 返回true或者false,bool型別 樣例 輸入 4,3,2,3,5,2,1 4 輸出 true 解釋 可以分解為4個子集,他們的和...