使用OpenMP多线程比单线程慢得多 我试图用OpenMP并行C++的神经网络训练过程。但它不会起作用。 然后我使用了一个简单的带有嵌套循环的C++代码来测试OpenMP。 但是OpenMP多线程比单线程慢得多。 我是不是做错了什么事情让它慢下来了?还是我错过了什么 系统

使用OpenMP多线程比单线程慢得多 我试图用OpenMP并行C++的神经网络训练过程。但它不会起作用。 然后我使用了一个简单的带有嵌套循环的C++代码来测试OpenMP。 但是OpenMP多线程比单线程慢得多。 我是不是做错了什么事情让它慢下来了?还是我错过了什么 系统,c++,multithreading,macos,parallel-processing,openmp,C++,Multithreading,Macos,Parallel Processing,Openmp,MacOS 4核 语言 C++ 时间函数 我使用了高分辨率时钟::now()和omp\u get\u wtime() std::chrono::高分辨率时钟::现在() 单线程成本时间:0.00000000000000 2线程成本时间:0.00010013580322 4线程成本时间:0.00016403198242 6线程成本时间:0.0001739188843 8线程成本时间:0.00112605094910 10线程成本时间:0.00013613700867 12线程成本时间:0.0008

MacOS 4核

语言 C++

时间函数 我使用了高分辨率时钟::now()omp\u get\u wtime()

  • std::chrono::高分辨率时钟::现在()
  • 单线程成本时间:0.00000000000000
    2线程成本时间:0.00010013580322
    4线程成本时间:0.00016403198242
    6线程成本时间:0.0001739188843
    8线程成本时间:0.00112605094910
    10线程成本时间:0.00013613700867
    12线程成本时间:0.00082898139954

  • omp_get_wtime()
  • 单线程成本时间:0.0000000 5900000
    2线程成本时间:0.00009097600000
    4线程成本时间:0.0001827300000
    6线程花费时间:0.00014479500000
    8线程成本时间:0.00070604400000
    10线程成本时间:0.0005727700000
    12线程成本时间:0.00074358000000

    代码
    #包括
    #包括
    #包括
    #包括
    使用名称空间std;
    无效测试(){
    int j=0;
    对于(int i=0;i<100000;i++){
    //做点什么消磨时间。。。
    j++;
    }
    };
    int main()
    {
    自动启动时间=时钟::高分辨率时钟::现在();
    自动结束时间=时钟::高分辨率时钟::现在();
    //没有openMp
    startTime=chrono::高分辨率时钟::现在();
    对于(int i=0;i<100000;i++){
    test();
    }
    endTime=chrono::高分辨率时钟::现在();
    时间::持续时间差=结束时间-开始时间;
    库特
    我试图用C++并行神经网络训练过程并行使用
    OpenMP。但是它不起作用。然后我用了一个简单的C++代码。
    用于测试OpenMP的嵌套循环

    我经常看到这一点;在代码中引入OpenMP,或者在这方面引入并行性,并不能神奇地使代码更快。

    为什么?因为有很多因素,但(在您的上下文中)因为并行完成的工作应该足够大,以克服并行的开销(例如线程创建、同步等)。要做到这一点,您需要增加并行任务的大小/数量

    另一个问题是对代码进行基准测试的方式:

    您的并行任务:

    void test() {
        int j = 0;
        for (int i = 0; i < 100000; i++) {
            // do something to kill time...
            j++; <---- Not enough work done in parallel 
        }
    };
    
    如果复制了很多次,最好只复制一次,然后从外部使用环境变量
    OMP_NUM_threads
    更改线程数

    关于您的更新:

    for (int k = 0; k < layer->map_count; k++) {
            for (int i = 0; i < map_h; i++) {
                for (int j = 0; j < map_w; j++) {
                    double max_value = prev_layer->map[k].data[2*i*upmap_w + 2*j];
                    for (int n = 2*i; n < 2*(i + 1); n++) {
                        #pragma omp parallel for
                        for (int m = 2*j; m < 2*(j + 1); m++) {
                             #pragma omp critical
                            max_value = MAX(max_value, prev_layer->map[k].data[n*upmap_w + m]);
                        }
                    }
                    layer->map[k].data[i*map_w + j] = activation_func::tan_h(max_value);
                }
            }
        }
    

  • 个人来说,这是一个旁注,不要误会,但我认为在盲目并行化代码之前,您应该先花更多的时间学习多线程和OpenMP的基础知识

  • 请不要继续用新问题更新原始问题。只需创建新问题即可


  • 您的测试循环实际上没有做任何事情,因此编译器可能正在删除它。那么您得到的时间主要是创建线程所花费的时间。测试函数应该返回值,您的代码应该将其打印到某个地方。正如@1201programalam所说,编译器可能会检测到您只是在浪费计算时间并删除循环。9女性不能在一个月内生孩子!您的计算时间太少,因此多线程非常有用。创建/结束线程需要时间。此外,请使用环境变量
    OMP\u NUM\u threads
    而不是
    NUM\u threads(…)
    @JérômeRichard关于最后一句话,我不确定它是否有效,因为OP有多个平行区域,具有不同数量的threads@dreamcrash是的,但我认为最好在专用脚本(如bash)中删除(基于复制过去的)基准测试代码.这在这里并不重要,因为该计划是一个基准。
    for (int k = 0; k < layer->map_count; k++) {
            for (int i = 0; i < map_h; i++) {
                for (int j = 0; j < map_w; j++) {
                    double max_value = prev_layer->map[k].data[2*i*upmap_w + 2*j];
                    for (int n = 2*i; n < 2*(i + 1); n++) {
                        #pragma omp parallel for
                        for (int m = 2*j; m < 2*(j + 1); m++) {
                             #pragma omp critical
                            max_value = MAX(max_value, prev_layer->map[k].data[n*upmap_w + m]);
                        }
                    }
                    layer->map[k].data[i*map_w + j] = activation_func::tan_h(max_value);
                }
            }
        }
    
    void test() {
        int j = 0;
        for (int i = 0; i < 100000; i++) {
            // do something to kill time...
            j++; <---- Not enough work done in parallel 
        }
    };
    
    // 2 threads
    startTime = chrono::high_resolution_clock::now();
    #pragma omp parallel for num_threads(2)
    for (int i = 0; i < 100000; i++) {
        test();
    }
    endTime = chrono::high_resolution_clock::now();
    diff = endTime - startTime;
    cout << "2 threads cost time: " << diff.count() << endl;
    
    for (int k = 0; k < layer->map_count; k++) {
            for (int i = 0; i < map_h; i++) {
                for (int j = 0; j < map_w; j++) {
                    double max_value = prev_layer->map[k].data[2*i*upmap_w + 2*j];
                    for (int n = 2*i; n < 2*(i + 1); n++) {
                        #pragma omp parallel for
                        for (int m = 2*j; m < 2*(j + 1); m++) {
                             #pragma omp critical
                            max_value = MAX(max_value, prev_layer->map[k].data[n*upmap_w + m]);
                        }
                    }
                    layer->map[k].data[i*map_w + j] = activation_func::tan_h(max_value);
                }
            }
        }
    
    for (int k = 0; k < layer->map_count; k++) {
            for (int i = 0; i < map_h; i++) {
                for (int j = 0; j < map_w; j++) {
                    double max_value = prev_layer->map[k].data[2*i*upmap_w + 2*j];
                    #pragma omp parallel for reduction(max: max_value)
                    for (int n = 2*i; n < 2*(i + 1); n++) {
                        for (int m = 2*j; m < 2*(j + 1); m++) {
                            max_value = MAX(max_value, prev_layer->map[k].data[n*upmap_w + m]);
                        }
                    }
                    layer->map[k].data[i*map_w + j] = activation_func::tan_h(max_value);
                }
            }
        }