multithreading - 性能下降:分叉代码与。openmp 代码
问题描述
我有使用 fork() 的并行代码来“读取灰度图像并将其转换为二进制”。我使用 openmp 将代码转换为多线程代码。但是,我注意到与使用 fork 的代码相比,openmp 代码的性能较差。我最初怀疑这可能是 openmp 开销,因此直接尝试使用 pthreads。但我注意到同样的模式。与分叉代码相比,pthread 代码的执行时间也更长。(注意:pthreads 比 openmp 略好几微秒)
以下是相同条件下的执行时间。
+-----------------+-------------+--------------+
| No. of children | using fork | using openmp |
+-----------------+-------------+--------------+
| 20 | 1.3 | 1.6 |
| 50 | 1.6 | 2.2 |
| 100 | 2.7 | 3.7 |
| 150 | 3.7 | 5.3 |
| 200 | 4.5 | 7.1 |
| 250 | 6.0 | 9.0 |
| 600 | 15.2 | 22.06 |
+-----------------+-------------+--------------+
编辑:添加代码。编译器:gcc-4.8.5,CPU 数量:256
由以下 2 个代码调用的函数:
void imgProcess(char* nam){
Pix *pixg = pixRead(nam);
Pix *pixb, *pixgray;
pixgray = pixConvertRGBToGray(pixg,0.33,0.33,0.34);
pixSauvolaBinarizeTiled(pixgray, 8, 0.34, 1, 1, NULL, &pixb);
pixDestroy(&pixg);
pixDestroy(&pixb);
}
使用 fork() 的代码:
int main() {
char prefix[60]="/root/Test/img_";
struct timespec i1, i2;
long long elapsed;
clock_gettime(CLOCK_MONOTONIC, &i1);
int count = 200;
for(int i=0; i<count; i++){
if(fork() == 0){
char filname[60];
sprintf(filname,"%s%d%s",prefix,i,".jpg");
imgProcess(filname);
exit(0);
}
}
for(int i=0; i<count; i++)
wait(NULL);
clock_gettime(CLOCK_MONOTONIC, &i2);
elapsed = i2.tv_sec*1000000000LL + i2.tv_nsec - i1.tv_sec*1000000000LL - i1.tv_nsec;
cout<<"Total : "<<(double)elapsed/1000000000LL<<endl;
return 0;
}
使用 openmp 的代码:
int main() {
int count = 200;
omp_set_num_threads(count);
char prefix[60]="/root/Test/img_";
struct timespec i1, i2;
long long elapsed;
clock_gettime(CLOCK_MONOTONIC, &i1);
#pragma omp parallel for
for(int j=0;j<count;j++){
char filname[60];
sprintf(filname,"%s%d%s",prefix,j,".jpg");
imgProcess(filname);
}
clock_gettime(CLOCK_MONOTONIC, &i2);
elapsed = i2.tv_sec*1000000000LL + i2.tv_nsec - i1.tv_sec*1000000000LL - i1.tv_nsec;
cout<<"Total : "<<(double)elapsed/1000000000LL<<endl;
return 0;
}
即使我接受,超出某个数量,forks() 会比线程快,根据这个线程,我仍然认为它们不会快几秒钟。
附加信息:我做了两个小测试。
- 第一个测试:我现在没有将上面的 imgProcess() 函数作为一个工作单元,而是将一个简单的“循环浪费时间”作为并行作业的一个工作单元,并注意到 openmp 和分叉代码的时间几乎相似。
第二个测试:我的并行作业的工作单元不是使用上面的 imgProcess() 函数作为工作单元,而是使用 C++ 流“读取文本文件”。在这种情况下,openmp 代码和分叉代码的时序也相似。
+---------+-------+--------+ | threads | fork | openmp | +---------+-------+--------+ | 20 | 0.018 | 0.008 | | 50 | 0.04 | 0.01 | | 100 | 0.08 | 0.04 | | 150 | 0.11 | 0.03 | | 200 | 0.16 | 0.07 | | 250 | 0.19 | 0.08 | +---------+-------+--------+
问题:
- 我的印象是线程和分叉应该具有相似的运行时。找出为什么多线程代码在不同情况下表现不同的任何想法?
- 到目前为止,我只是用线程替换了 fork() 部分。实际上有一个并行化灰度到二进制图像转换算法本身的范围,我还没有这样做。看到上面的时间,我觉得继续并行化算法可能没有用。你有什么建议?你觉得并行化可能有用吗?
解决方案
推荐阅读
- integral - 绘制由参数积分定义的函数
- python - %H:%M:%S.%f 格式在我的熊猫数据框中不一致
- jspdf - jsPDF图像在错误的页面上一直以错误的顺序显示
- java - 每当我在色轮外滑动时,我的应用程序就会崩溃
- python - PyAudio 如何将频率范围分组在一起
- php - 客户使用礼品卡付款时绕过“计费”部分 - woocommerce
- objective-c - 在 Objective-C 中公开 Swift 枚举数组
- sql - 我想在每个相同的日期汇总数据
- javascript - 在云中存储变量的最佳方法是什么?
- sql - 如何从 db2 中的 xml 字符串中读取值