有没有让c ++代码运行得更快,我试图优化我的代码中最慢的部分,如:
void removeTrail ( char floor[][SIZEX],int trail[][SIZEX])
{
for (int y=1; y < SIZEY-1; y++)
for (int x=1; x < SIZEX-1; x++)
{ if (trail [y][x] <= SLIMELIFE && trail [y][x] > 0)
{ trail [y][x] --;
if (trail [y][x] == 0)
floor [y][x] = NONE;
}
}
}
我在网上找到的大部分指南都是针对更复杂的C ++。
答案 0 :(得分:1)
这实际上取决于您所寻求的优化类型。在我看来,你正在谈论一个更“低级”的优化,可以通过结合编译标志,通过改变嵌套循环的顺序,改变放置{{1}的位置等技术来实现}语句,在递归方法和迭代方法之间做出决定等等。
但是,最有效的优化是那些针对算法的优化,这意味着您正在改变例程的复杂性,因此通常会将执行时间减少几个数量级。例如,当您决定实施Quicksort而不是Selection Sort时就是这种情况。从O(n ^ 2)到O(n lg n)算法的优化几乎不会受到任何微优化的影响。
在这种特殊情况下,我发现当你达到某个值时,你试图从矩阵中“删除”元素。根据这些值的变化情况,只需跟踪它们到达时间并将其添加到queue以便在那里删除,而不是始终检查整个矩阵,可能会这样做:
if
根据这些值的变化方式(如果它不是简单的trail[y][x]--; // In some part of your code, this happens
if (trail[y][x] == 0) { //add for removal
removalQueueY[yQueueTail++] = y;
removalQueueX[xQueueTail++] = x;
}
//Then, instead of checking for removal as you currently do:
while (yQueueHead < yQueueTail) {
//Remove the current element and advance the heads
floor[removalQueueY[yQueueHead]][removalQueueX[xQueueHead]] = NONE;
yQueueHead++, xQueueHead++;
}
),另一个数据结构可能会更有用。您可以尝试使用heap或trail[y][x]--
,std::set
等其他可能性。这一切都归结为算法必须支持的操作,以及哪些数据结构允许您尽可能高效地执行这些操作(考虑内存和执行时间,具体取决于您的优先级和需求)。
答案 1 :(得分:0)
要做的第一件事是打开编译器优化。我所知道的最强大的优化是配置文件引导优化。对于gcc:
1)g ++ -fprofile-generate .... -o my_program
2)运行my_program(典型负载)
3)g ++ -fprofile-use -O3 ... -o optimized_program
使用配置文件O3确实有意义。
接下来就是执行算法优化,就像Renato_Ferreira的回答一样。如果它不适用于您的情况,您可以使用矢量化将性能提高2倍。您的代码看起来可以矢量化:
#include <cassert>
#include <emmintrin.h>
#include <iostream>
#define SIZEX 100 // SIZEX % 4 == 0
#define SIZEY 100
#define SLIMELIFE 100
#define NONE 0xFF
void removeTrail(char floor[][SIZEX], int trail[][SIZEX]) {
// check if trail is 16 bytes alligned
assert((((size_t)(&trail[0][0])) & (size_t)0xF) == 0);
static const int lower_a[] = {0,0,0,0};
static const int sub_a[] = {1,1,1,1};
static const int floor_a[] = {1,1,1,1}; // will underflow after decrement
static const int upper_a[] = {SLIMELIFE, SLIMELIFE, SLIMELIFE, SLIMELIFE};
__m128i lower_v = *(__m128i*) lower_a;
__m128i upper_v = *(__m128i*) upper_a;
__m128i sub_v = *(__m128i*) sub_a;
__m128i floor_v = *(__m128i*) floor_a;
for (int i = 0; i < SIZEY; i++) {
for (int j = 0; j < SIZEX; j += 4) { // only for SIZEX % 4 == 0
__m128i x = *(__m128i*)(&trail[i][j]);
__m128i floor_mask = _mm_cmpeq_epi32(x, floor_v); // 32-bit
floor_mask = _mm_packs_epi32(floor_mask, floor_mask); // now 16-bit
floor_mask = _mm_packs_epi16(floor_mask, floor_mask); // now 8-bit
int32_t fl_mask[4];
*(__m128i*)fl_mask = floor_mask;
*(int32_t*)(&floor[i][j]) |= fl_mask[0];
__m128i less_mask = _mm_cmplt_epi32(lower_v, x);
__m128i upper_mask = _mm_cmplt_epi32(x, upper_v);
__m128i mask = less_mask & upper_mask;
*(__m128i*)(&trail[i][j]) = _mm_sub_epi32(x, mask & sub_v);
}
}
}
int main()
{
int T[SIZEY][SIZEX];
char F[SIZEY][SIZEX];
for (int i = 0; i < SIZEY; i++) {
for (int j = 0; j < SIZEX; j++) {
F[i][j] = 0x0;
T[i][j] = j-10;
}
}
removeTrail(F, T);
for (int j = 0; j < SIZEX; j++) {
std::cout << (int) F[2][j] << " " << T[2][j] << '\n';
}
return 0;
}
看起来它做了它想做的事情。没有ifs和4个迭代值。仅适用于NONE = 0xFF。可以为另一个人做,但很难。