Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenMP第一个内核比第二个内核慢得多_C++_C_Multithreading_Parallel Processing_Openmp - Fatal编程技术网

C++ OpenMP第一个内核比第二个内核慢得多

C++ OpenMP第一个内核比第二个内核慢得多,c++,c,multithreading,parallel-processing,openmp,C++,C,Multithreading,Parallel Processing,Openmp,我有一个巨大的98306乘98306二维数组初始化。我创建了一个内核函数,它计算低于某个阈值的元素总数 #pragma omp parallel for reduction(+:num_below_threshold) for(row) for(col) index = get_corresponding_index(row, col); if (array[index] < threshold) num_below_thre

我有一个巨大的98306乘98306二维数组初始化。我创建了一个内核函数,它计算低于某个阈值的元素总数

#pragma omp parallel for reduction(+:num_below_threshold)
for(row)
    for(col)
        index = get_corresponding_index(row, col);
        if (array[index] < threshold)
            num_below_threshold++;
#pragma omp parallel用于缩减(+:num_低于_阈值)
(世界其他地区)
用于(col)
索引=获取对应的索引(行、列);
if(数组[索引]<阈值)
num_低于_阈值++;
出于基准测试的目的,我测量了线程数设置为1时执行的内核的执行时间。我注意到内核第一次执行它大约花了11秒。下一次对内核的调用只花了大约3秒的时间,该调用使用一个线程在同一阵列上执行。我认为这可能是一个与缓存有关的问题,但似乎没有关系。造成这种情况的可能原因是什么

此数组初始化为:

float *array = malloc(sizeof(float) * 98306 * 98306);
for (int i = 0; i < 98306 * 98306; i++) {
    array[i] = rand() % 10;
}
float*array=malloc(sizeof(float)*98306*98306);
对于(int i=0;i<98306*98306;i++){
数组[i]=rand()%10;
}

同一内核被应用于这个数组两次,第二次执行时间比第一次内核快得多。我认为Linux上的延迟分配是有问题的,但由于初始化函数的缘故,这不应该是一个问题。任何解释都会有帮助。谢谢

既然你没有提供任何信息,我不得不在这里做一些大胆的猜测,但我很有信心我掌握了问题的要点

首先,您必须注意98306 x 98306是9664069636,这远远大于有符号32位整数可以存储的最大值(2147483647)。因此,溢出后,初始化循环的
上限可能会变为1074135044(就像在我的机器上一样,尽管严格来说这是未定义的行为,任何事情都可能发生),这大约比您预期的小9倍

现在,在初始化循环之后,操作系统实际上只分配了您认为分配的内存的11%。然而,您的第一个简化循环在检查阵列的各个元素方面做得很好,因为对于其中的大约89%来说,这是第一次,操作系统在那里进行实际的内存分配,这需要相当长的时间

现在,对于您的第二个简化循环,所有内存都已正确分配和使用,这使它更快

这就是我认为发生的事情。也就是说,许多其他参数可以在这里发挥作用,例如:

  • 交换:尝试分配的阵列表示大约36GB的内存。如果您的机器没有那么多可用内存,那么您的代码可能会被交换,这可能会使您能够提出的任何性能度量都变得一团糟
  • NUMA效应:如果您的计算机有多个NUMA节点,那么线程固定和内存关联如果管理不当,可能会对循环之间的性能产生很大影响
  • 编译器优化:您没有提到您使用的编译器以及您请求的优化级别。有鉴于此,你会惊讶于你的代码会变得多么简短。例如,编译器可以完全删除第二个循环,因为它执行与第一个相同的操作,并且由于结果相同而变得无用。。。还有许多其他让你的基准变得毫无意义的有趣和意想不到的事情

贴一张照片。特别是,你是如何初始化数组的?@EOF我添加了这个例子。但是我没有看到数组的初始化方式对执行结果的影响。有符号整数溢出是未定义的行为,因此编译器可以完全删除代码。@EOF很好。我添加了一个注释提到它(尽管我仍然很有信心事情和我描述的一样),似乎编译器优化是问题发生的原因。出于某种原因,编译器决定将简化操作更改为原子添加。这就完全不同了。