我有一个像
一样的算法int sumLargest2 ( int * arr, size_t n )
{
int largest(max(arr[0], arr[1])), secondLargest(min(arr[0],arr[1]));
// ...
并且我意识到第一个可能不是最优的,因为当您认为在找到最大值后知道最小值所需的信息已经存在时,调用max
然后min
是重复的。所以我发现我可以做到
int largest = max(arr[0], arr[1]);
int secondLargest = arr[0] == largest ? arr[1] : arr[0];
去除min
无用的调用,但我不确定实际上是否会保存任何数量的操作。是否有任何奇特的位移算法可以完成相同的
int largest(max(arr[0], arr[1])), secondLargest(min(arr[0],arr[1]));
···
答案 0 :(得分:10)
在C ++中,您可以使用std::minmax
生成最小值和最大值SELECT Person.FirstName, Person.LastName, Person.Phone, Person.Email, Person.Address, Count(*) as Result <br>
From Table1 join table 2 -- etc <br>
WHERE a = b -- etc <BR>
GROUP BY Person.FirstName, Person.LastName, Person.Phone, Person.Email, Person.Address
。与std::tie
:
std::pair
GCC至少能够将对minmax的调用优化为单个比较,与下面的C代码的结果相同。
在C中,你可以自己编写测试:
#include <algorithm>
#include <utility>
int largest, secondLargest;
std::tie(secondLargest, largest) = std::minmax(arr[0], arr[1]);
答案 1 :(得分:4)
怎么样:
int largestIndex = arr[1] > arr[0];
int largest = arr[largestIndex];
int secondLargest = arr[1 - largestIndex];
第一行依赖于布尔结果的隐式强制转换,在真实的情况下为1,在假的情况下为0。
答案 2 :(得分:4)
如果您打算减少函数调用以查找min mad max,则可以尝试std::minmax_element
。这是从C ++ 11开始提供的。
auto result = std::minmax_element(arr, arr+n);
std::cout<< "min:"<< *result.first<<"\n";
std::cout<< "max :" <<*result.second << "\n";
答案 3 :(得分:4)
我会假设您宁愿解决更大的问题......也就是说,得到数组中最大的两个数字之和。
您要做的是std::partial_sort()
。
让我们来实现它。
$route['auth/(:any)/(:num)'] = "bit_auth/$1/$2";
如果您无法修改int sumLargest2(int * arr, size_t n) {
int * first = arr;
int * middle = arr + 2;
int * last = arr + n;
std::partial_sort(first, middle, last, std::greater<int>());
return arr[0] + arr[1];
}
,那么我建议您查看std::partial_sort_copy()
。
答案 4 :(得分:4)
x = max(a, b);
y = a + b - x;
它不一定会更快,但会有所不同。
还要注意溢出。
答案 5 :(得分:3)
如果您只想找到两个值中较大的值,请执行:
if(a > b)
{
largest = a;
second = b;
}
else
{
largest = b;
second = a;
}
无函数调用,一次比较,两次分配。
答案 6 :(得分:2)
如何进行时空权衡?
zip_code city
210 Boston
211 Boston
212 .
1431 .
答案 7 :(得分:2)
我假设是C ++ ......
简短回答,使用std :: minmax并使用正确的优化和正确的指令集参数进行编译。
长期难看的答案,编译器无法做出必要的所有假设,以使其真正,非常快。您可以。在这种情况下,您可以更改算法以首先处理所有数据,并且可以强制对齐数据。完成所有这些操作后,您可以使用内在函数来加快速度。
虽然我没有在这种特殊情况下测试它,但我已经看到使用这些指南的巨大性能改进。
由于你没有将2个整数传递给函数,我假设你使用了一个数组,并想以某种方式迭代它。您现在可以选择:制作2个数组并使用最小值/最大值或使用1个阵列同时使用a
和b
。仅这一决定已经可以影响绩效。
如果你有2个数组,可以使用对齐的malloc在32字节边界上分配这些数组,然后使用内在函数进行处理。如果你想要真正的原始表现 - 这是要走的路。
F.ex,我们假设你有AVX2。 (注意:我不确定你是否这样做,你应该使用CPU ID来检查它!)。转到这里的备忘单:https://software.intel.com/sites/landingpage/IntrinsicsGuide/并挑选你的毒药。
您正在寻找的内在函数可能是:
如果必须为整个数组执行此操作,则可能需要在合并各个项之前将所有内容保留在单个__mm256寄存器中。例如:每256位向量执行一次最小值/最大值,当循环完成时,提取32位项并对其进行最小值/最大值。
更好的答案:所以...至于编译器。编译器会尝试优化这些类型的东西,但会遇到问题。
如果您处理了2个不同的数组,编译器必须知道它们是不同的才能进行优化。这就是为什么像restrict这样的东西存在的原因,它告诉编译器你编写代码时可能已经知道的这个小东西。
此外,编译器不知道您的内存是否已对齐,因此必须检查此内容并为每次调用分支....我们不希望这样;这意味着我们希望它能够内联它的内容。所以,添加inline
,将其放在头文件中即可。您也可以使用aligned
给他一个提示。
您的编译器也没有得到int*
不会随时间变化的提示。如果无法更改,最好告诉他使用const
关键字。
编译器使用指令集进行编译。通常情况下,他们已经使用了SSE,但AVX2可以提供很多帮助(正如我上面用内在函数所示)。如果可以使用这些标志进行编译,请确保使用它们 - 它们有很多帮助。
在发布模式下运行,在'fast'上进行优化编译,看看底层会发生什么。如果你这样做,你应该看到内部循环中出现vpmax...
指令,这意味着编译器使用内在函数就好了。
我不知道你想在循环中做什么...如果你使用所有这些指令,你应该在大数组上达到内存速度。