我的第一個答案解決問的實際問題,並修復了awk
腳本。但也許我錯過了這一點。如果你想要速度,並且不介意更多地使用你的多核處理器,你可以使用GNU parallel。下面是一個將同時啓動4個就業機會的實現:
awk_cmd='$4 > var - 5 && $4 < var + 5 { print $10, $4 }'
parallel -j 4 "awk -v var={} '$awk_cmd' INFILE" :::: LISTFILE
正如你所看到的,這將讀取INFILE
最多同時四倍。這個答案在調整作業數量之後,應該提供與您在shell中描述的並行實現非常相似的性能。因此,您可能希望將您的LISTFILE
分成更小的塊,並將awk_cmd
設置爲我在先前答案中發佈的命令。可能有一個最佳的方式來處理您的輸入,但這主要取決於INFILE
的大小和LISTFILE
中的元素數量。 HTH。
測試:
創建LISTFILE
:
paste - - < <(seq 16) > LISTFILE
創建INFILE
:
awk 'BEGIN { for (i=1; i<=9999999; i++) { print i, i, i, int(i * rand()), i, i, i, i, i, i } }' > INFILE
結果:
測試1:
time awk 'FNR==NR { a[$2]; next } { for (i in a) { if ($4 > i - 5 && $4 < i + 5) { print $10, $4 } } }' LISTFILE INFILE >/dev/null
real 0m45.198s
user 0m45.090s
sys 0m0.160s
測試2:
time for i in $(seq 1 2 16); do awk -v var="$i" '$4 > var - 5 && $4 < var + 5 { print $10, $4 }' INFILE; done >/dev/null
real 0m55.335s
user 0m54.433s
sys 0m0.953s
TEST3:
awk_cmd='$4 > var - 5 && $4 < var + 5 { print $10, $4 }'
time parallel --colsep "\t" -j 4 "awk -v var={2} '$awk_cmd' INFILE" :::: LISTFILE >/dev/null
real 0m28.190s
user 1m42.750s
sys 0m1.757s
我對THIS答案回覆:
1:
The awk1 script does not run much faster than the awk script.
有15%的時間節約在我看來是非常顯著。
I suspect because it scans the LISTFILE for every line in the INFILE.
是的,本質上。 awk1
腳本只通過INFILE
循環一次。
So number of lines scanned using the array with for (i in a) = NR(INFILE)*NR(LISTFILE).
關閉。但不要忘記,通過使用數組,我們實際上刪除了LISTFILE
中的任何重複值。因此
This is the same number of lines you would scan by going through the INFILE repeatedly with the bash script.
這種說法是唯一真正當LISTFILE
不包含重複。即使LISTFILE
從不包含任何嘟嘟聲,最好避免不得不多次讀取單個文件。
2:
Running awk and awk2 in a different folder produced different results (where my 4 min result came from versus the ~2 min result here, not sure what the difference is because they are next door in the parent directory.
哪四個分鐘出結果?在對這類事情進行基準測試時,應該停止將輸出寫入磁盤。如果您的機器在運行測試時有一些後臺進程正在進行,那麼您最終只會以磁盤的寫入速度對結果進行偏置。改爲使用/dev/null
。
3:
Awk and Awk2 are essentially the same. Any idea why awk2 runs faster?
如果刪除管sort
和uniq
你會得到的時間差就是一個更好的主意。你會發現做$4 > i - 5 && $4 < i + 5
與做$4 < i + 5 && $4 > i - 5
完全不同。如果awkout.txt
與awkout.txt
相同,則需要花費時間處理重複項。
4:
你張貼在這裏的第二個命令可以避免這個測試:$4 > i - 5 && $4 < i + 5
。我不認爲僅憑這一點就能保證運行時間提高90%。有什麼東西聞到錯誤。您是否願意將您的測試重新寫入/dev/null
併發布LISTFILE
和INFILE
的內容?如果這兩個文件是保密的,您能否提供一些內容數量與原件相同的示例文件?
其他的想法:
對我來說,它看起來像東西沿着這些路線也將工作:
awk 'FNR==NR { for (i=$2-4;i<$2+5;i++) a[i]; next } $4 in a { b[$10,$4] } END { print length b }' LISTFILE INFILE
我已經發布了我的結果並在下面回覆了答案。 – jeffpkamp
@jeffpkamp:我已在上述問題中添加了回覆。 HTH。 – Steve
啊,那最後的功能就是我從一開始就在尋找的東西!我調整了它的結尾「{b [$ 10,$ 4] ++} END {for(i in b)print i,b [i]}」This subs for my sort | uniq -c功能步驟仍然只需要12秒鐘。我認爲運行時間增加90%是因爲只讀取一次文件(讀取8 + 2000萬行),而不是循環讀取每行文件(讀取8 * 2000萬行),因此運行速度提高了8倍。謝謝您的幫助。 – jeffpkamp