我在這里嘗試做的是理解 OpenMP,所以我撰寫了一個簡單的程式,它比較了矩陣向量乘法的并行化計算時間。它以不同大小的矩陣(1024、2048、8192)、不同數量的執行緒(1、2、4、8)和不同的調度策略(靜態、動態、引導)運行。我在具有兩個內核和 4 個執行緒的機器上運行該程式。
時間是:
1 個執行緒有 1024 個條目和調度的時間 0:26720 個滴答
1 個執行緒有 8192 個條目和調度的時間 0:1486755 個滴答
2 個執行緒有 1024 個條目和調度的時間 0:159161 個滴答
2 個執行緒有 8192 個條目的時間和調度 0: 22254787 滴答
但這沒有意義,當執行緒從 1 增加到 2 時,cpu 滴答的數量會增加大約 5 到 15 倍。4 執行緒和 8 執行緒的時間再次好一點。
代碼是
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef _OPENMP
#include <omp.h>
#else
#define omp_get_thread_num() 0
#endif
void matrix(unsigned int n)
{
// The big arrays we want on the heap
float *matrix = (float *)malloc(sizeof(float) * n * n);
float *vector = (float *)malloc(sizeof(float) * n);
float *result = (float *)malloc(sizeof(float) * n);
#pragma omp parallel for
// initialize matrix
for (int row = 0; row < n; row )
{
for (int column = 0; column < n; column )
{
*(matrix (row * n) column) = rand();
}
}
// initialize vectors
#pragma omp parallel for
for (int row = 0; row < n; row )
{
*(vector row) = rand();
*(result row) = 0;
}
// multiply
#pragma omp parallel for
for (int row = 0; row < n; row )
{
for (int column = 0; column < n; column )
{
float resultat = *(matrix (row * n) column) * *(vector column);
*(result row) = resultat;
}
}
}
int main()
{
time_t t_t;
// Initialisieren Zufallsgenerator
srand((unsigned)time(&t_t));
unsigned int threads[] = {1, 2, 4, 8};
unsigned int amounts[] = {1024, 2048, 8192};
omp_sched_t schedules[] = {omp_sched_static,
omp_sched_dynamic,
omp_sched_guided};
size_t size_threads = sizeof(threads) / sizeof(threads[0]);
size_t size_amounts = sizeof(amounts) / sizeof(amounts[0]);
size_t size_schedules = sizeof(schedules) / sizeof(schedules[0]);
// Anzahl Threads variieren
for (int t = 0; t < size_threads; t )
{
omp_set_num_threads(threads[t]);
for (int a = 0; a < size_amounts; a )
{
for (int s = 0; s < size_schedules; s )
{
omp_set_schedule(schedules[s], 0);
clock_t start_t = clock();
matrix(amounts[a]);
clock_t end_t = clock();
printf("Time for %d threads with %d entries and scheduling %d: %ld ticks\n\a", threads[t], amounts[a], s, (end_t - start_t));
}
}
}
return 0;
}
我的代碼中是否有錯誤或對此行為的其他解釋?
編輯:我也嘗試過 gettimeofday() 函式,如
struct timeval start_time;
struct timeval end_time;
...
gettimeofday(&start_time, NULL);
matrix(amounts[a]);
gettimeofday(&end_time, NULL);
...
printf("Time for %d threads with %d entries and scheduling %d: %f s\n\a", threads[t], amounts[a], s, (double)(end_time.tv_sec - start_time.tv_sec) (double)(end_time.tv_usec - start_time.tv_usec)/1000000);
結果基本相同:
1 個執行緒有 1024 個條目和調度的
時間0:0.024589 秒1 個執行緒有 8192 個條目和調度的
時間0:1.393275 秒2 個執行緒有 1024 個條目和調度的
時間0:0.117452 秒2 個執行緒有81092 個條目和調度的時間: 25.067069 秒
uj5u.com熱心網友回復:
我認為這與以下問題有關: OpenMP time 和 clock() 給出兩種不同的結果
問題是,可能會clock()回傳花費在 CPU 上的總時間,隨著更多執行緒處于活動狀態,該時間會變得更多。實際花費的時間與該數字沒有太大關系。我建議使用gettimeofday()函式來測量實時并將結果與clock().
uj5u.com熱心網友回復:
另一個問題是 OpenMP 有設定執行緒和在執行緒之間分配作業的開銷。您需要合理的作業量,否則開銷會大于并行化帶來的收益。
uj5u.com熱心網友回復:
除了所說的之外,記憶體爭用可能也起作用,受 L1 和 L2 快取量的影響
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/335267.html
上一篇:我們如何在C編程中將10陣列中最大的5個數字替換為1,最小的5替換為0?
下一篇:為什么位移位在C中是這樣寫的?
