我想知道是否有人建议我可以做些什么来提高代码的运行速度。我写了一个Sieve of Atkin
函数,它返回一个向量,包括来自[2, max]
的所有素数。
这是我的代码。
void atkin_sieve (unsigned int max, std::vector <unsigned int> & primes) {
// Sieve array up to max defaulted to false
// Index's [0, max] correspond to numbers
// Dynamic memory so all values default false
bool* sieve = new bool [max + 1];
// Square root of max number
unsigned int sqrt_max = int (sqrt (max));
// Unsigned integers declared to save time
unsigned int n, x, y;
// TODO - Explain this
for (x = 1; x < sqrt_max; x++) {
for (y = 1; y < sqrt_max; y++) {
n = (4 * x * x) + (y * y);
if (n <= max && (n % 12 == 1 || n % 12 == 5))
sieve [n] = !sieve [n];
n = (3 * x * x) + (y * y);
if (n <= max && (n % 12 == 7))
sieve [n] = !sieve [n];
n = (3 * x * x) - (y * y);
if (x > y && n <= max && (n % 12 == 11))
sieve [n] = !sieve [n];
}
}
// TODO - Explain this
for (x = 5; x < sqrt_max; x++) {
if (sieve [x]) {
n = x * x;
for (y = n; y <= max; y += n)
sieve [y] = false;
}
}
// Push primes 2, 3, and 5
primes.push_back(2);
primes.push_back(3);
primes.push_back(5);
// Start from prime 7, skip even numbers
for (x = 7; x <= max; x += 2) {
// If the number is prime
if (sieve [x])
// Push it into the vector
primes.push_back(x);
}
// Delete the sieve array
delete [] sieve;
}
我有一些问题,关于我可以做些什么来优化这个功能。
我将筛子阵列初始化为一个动态的布尔数组,这样它们都会默认为假,筛子是否像这样动态更快或者我应该将它保持为正常数组?
我在算法处理后使用for循环将素数存储在矢量中,是否有更快的方法可以找到筛子中的所有素数以将它们存储在矢量中?
欢迎任何其他提示,技巧,提示或代码,非常感谢,谢谢。
答案 0 :(得分:0)
根据您返回的素数,使用std::vector
可能会导致问题,每次向量必须增长以处理比其容量更多的对象时,可能需要创建一个新数组并复制所有从旧数组到新数组的值。请考虑使用std::list
或std::deque
来避免此问题。如果你确实需要一个vector
,那么循环并计算素数的数量可能会更快,然后reserve
在向量中有更大的数量,这样向量就不需要增长。
您应该对代码进行一些分析 - 如何执行此操作取决于您的开发环境。这应该告诉您代码的大部分时间花在哪里。如果没有这些信息,您可以花费多年时间优化代码的一部分,因为它不会对结果产生巨大影响。
至少添加一些计时代码,这样你就可以看到你所做的任何改变是否有用,以及提供了多少。
最好的优化通常是改变算法,通常做循环展开等事情最好留给编译器,除非代码特别关键时间(即使那时可能没有)。
此外,请确保您正在进行优化编译 - 这可能会产生巨大的差异。
答案 1 :(得分:0)
正如另一个答案所暗示的那样,分析是解决时间问题的最佳方法。
一些建议和评论,其中一些可能很明显
我不相信你实际上已经保证在你的筛子分配上没有初始化;为此,您需要使用bool *sieve = new bool[max+1]();
。如果您发现事情正常,那么您在这里要么幸运,要么在编译器下运行,以便初始化调试版本。如果是这种情况,请尝试启用优化的版本构建,并且您会看到一些加速。
您的bool[]
很可能不会每个元素使用1位,但可能是一个字节。您可能会发现使用std::vector<bool>
效率更高,因为它通常专门用于密集存储布尔值 - 每个布尔1位。您将减少内存占用,而不是增加读/写单个布尔值的复杂性。
尝试使用适当的输入验证将素数数组预先调整为max / log(max)
,作为小于最大值的素数的近似值。
如果在您的应用程序中重复调用该函数,请尝试重复使用以前的筛选阵列来应答后续调用。