sách gpt4 ai đã đi

openmp - 如何统计测量程序中的 OpenMP 性能?

In lại 作者:行者123 更新时间:2023-12-03 18:15:50 29 4
mua khóa gpt4 Nike

我想统计测量与 OpenMP 并行化的程序的性能。我选择在执行并行算法的测试应用程序中编写循环 MAX_EXPERIMENTS次并将时间测量报告到文件中。

问题解决方案似乎比提取外部循环上方的并行编译指示更复杂,因为我在内部并行循环之间有代码的串行部分。

编码:

#include 
#include
#include
#include
#include
#include
#include
#include

sử dụng không gian tên std;

int chính()
{
const int MAX_NUMBERS = 1e07;
const int MAX_EXPERIMENTS = 1e02;

std::random_device rd;
std::mt19937 gen(rd());
std::bernoulli_distribution dis(0.1);

vector numbers;
numbers.reserve(MAX_NUMBERS);

for(unsigned int i = 0; i < MAX_NUMBERS; ++i)
{
if (dis(gen))
numbers.emplace_back(100);
khác
numbers.emplace_back(1);
}

stringstream ss;
ss << "time-measurements-nthread-" << setfill('0') << setw(2)
<< omp_get_max_threads() << ".csv";

ofstream exp(ss.str());
exp << "time\n";

for (unsigned int i = 0; i < MAX_EXPERIMENTS; ++i)
{
// BEGIN: Tested parallel program
double t0 = omp_get_wtime();

// Some serial work.

double x = 0;
//#pragma omp parallel for schedule(dynamic) reduction(+:x) // exp-01
#pragma omp parallel for schedule(static) reduction(+:x) // exp-02
for(unsigned int i = 0; i < numbers.size(); ++i)
{
if (numbers[i] > 1)
x = x + cos(numbers[i]); // Some work being done.
}
double t1 = omp_get_wtime();

// Some serial work

// Measure program execution
exp << t1 - t0 << "\n";

// END: Tested parallel program
}

};

程序首先串行初始化 1e07号码为 1hoặc 100使得命中 100的概率是 10% ,这与我真实世界的输入数据相匹配。

主测试循环执行 100实验,并且循环体模型测试了并行算法。并行算法的某些部分必须串行执行。写作 pragma omp parallel for在循环中应该是一个坏主意,因为每次创建实验时它都会打开和关闭线程。

问题 1 :即使通常人们会避免在循环内打开并行区域,在这种情况下是否合理,其中每个实验循环步骤代表一个独立的并行程序执行,并且在运行时为实验准备输入数据的速度要快得多?

为了可视化写入的数据,我使用了 python(jupyter nootebook 代码):
%matplotlib inline

nhập pandas dưới dạng pd
nhập matplotlib.pyplot dưới dạng plt
from matplotlib import rcParams
nhập khẩu hệ điều hành

rcParams["figure.figsize"] = [10,20]
rcParams["font.size"] = 24

def plot_experiment(expattern):
thread1df = pd.read_csv("time-measurements-nthread-01-%s.csv" % expattern)
thread2df = pd.read_csv("time-measurements-nthread-02-%s.csv" % expattern)
thread4df = pd.read_csv("time-measurements-nthread-04-%s.csv" % expattern)
thread8df = pd.read_csv("time-measurements-nthread-08-%s.csv" % expattern)


f, (ax1, ax2) = plt.subplots(2, 1, sharex=True)

ax1.plot(thread1df["time"], label="time 1", color='g')
ax1.plot(thread2df["time"], label="time 2", color='r')
ax1.plot(thread4df["time"], label="time 4", color='b')
ax1.plot(thread8df["time"], label="time 8", color='k')

ax2.plot(thread1df["time"] / thread8df["time"], label="speedup 8", color='k')
ax2.plot(thread1df["time"] / thread4df["time"], label="speedup 4", color='b')
ax2.plot(thread1df["time"] / thread2df["time"], label="speedup 2", color='r')

ax1.set_ylabel("Time in seconds")
ax1.huyền thoại()

ax2.set_xlabel("Test number")
ax2.huyền thoại()
ax2.set_ylabel("Speedup")


plot_experiment("exp-01")

并且应用程序是用gcc编译的,使用优化: g++ -std=c++1y -fopenmp -O3 main.cpp -o main
实验使用 for i in 1 2 4 8; do export OMP_NUM_THREADS=$i && ./main && sleep 5; done; thực hiện

然后使用 for file in *nthread-0[0-9].csv*; do mv $file ${file/.csv/-exp-02.csv}; done 为 Pandas 重新命名实验文件(在第一个实验中将 exp-02 替换为 exp-01).

在第一个实验中,我尝试了动态调度,得到如下图:

nhập mô tả hình ảnh ở đây

这很奇怪,因为添加线程似乎会减慢程序的速度。使用 HPCToolkit 检查瓶颈为 exp-018线程,我注意到 OpenMP 花费了大量时间在 dynamic 中进行切换。调度模式:

nhập mô tả hình ảnh ở đây

所以我把调度模式切换到 tĩnh并重新运行实验,然后得到以下结果:

nhập mô tả hình ảnh ở đây

现在有一些扩展,至少对于 2线程,但现在 4线程振荡太多,使用 8效果不大线程。我使用 HPCToolkit 检查了它再次得到这个:

nhập mô tả hình ảnh ở đây

我认为这告诉我启动和停止线程正在消耗 85%我的运行时 8线程,但是 HPCToolkit 手册指出

Furthermore, if the filtered nodes are children of a “fake” procedures (such as program_root and thread_root), the exclusive metrics in callers view and flat view can be misleading.



问题 2 : 实验02在实验循环内打开和关闭并行区域是否有显着开销?如果是这样,考虑到算法的串行部分,如何解决这个问题?

软件:Arch Linux,g++ (GCC) 7.1.1 20170630,hpcrun:HPCToolkit 成员,版本 2017.11,CPU:Intel(R) Core(TM) i7-4710HQ CPU @ 2.50GHz

biên tập

我尝试使用建议的环境变量更改线程持久性行为 in the answer to this question :
export OMP_WAIT_POLICY=active GOMP_SPINCOUNT=infinite

Sau đây là kết quả:

nhập mô tả hình ảnh ở đây

显然,由线程创建/销毁引起的振荡要低得多,但它们消失了吗?有没有办法改变程序,这样我就不必依赖自旋线程?调查此程序的瓶颈仍将显示自旋线程花费了大量 CPU 周期。

1 Câu trả lời

从评论中的讨论来看,您的主要问题似乎是您有一个复杂的现有应用程序,并希望在某个内部部分放置一个工作共享循环。但是仅创建所有线程在您的应用程序中有太多开销,libgomp 的线程池似乎不够。

如果你想在不重组的情况下做到这一点,使用 taskloop 可能会有所帮助。 ,其作用类似于 ,但可以嵌套在 single 中部分。反过来,它可能不如`for 那样有效。基本上你的代码看起来像这样:

số nguyên a;
#pragma omp parallel
{
int b;
#pragma omp single
{
số nguyên c;
// lots of serial code
// somewhere inbetween
#pragma omp taskloop
for (...) {
int d;
}
// lots of serial code
}
}

请注意,任务生成结构的数据共享工作方式略有不同。默认情况下,在并行区域( Một )之外声明的变量是 sharedsong song区域,并在执行内循环的任务之间共享。在并行区域内声明的变量,但在 taskloop 之外( b , c ), 是 riêng tư平行区域内和 firstprivate - 即每个线程都有自己的副本,该副本使用外部值进行初始化。最后 ngày只是每个循环迭代的局部。

编辑:不要设置任何障碍。由于隐式任务组,串行部分和任务在执行中是隔离的。

关于openmp - 如何统计测量程序中的 OpenMP 性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48303120/

29 4 0
行者123
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com