我有一系列不断增长的输入值,我想分析它的运行时间。
int main(){
srand(time(NULL)); //initialize random num generator with time(NULL) as seed
int size_arr[7] = {1000, 10000, 25000, 50000, 100000, 150000, 200000};
// int size_arr[6] = {1000, 10000, 25000, 50000, 100000, 129992};
int size = (sizeof(size_arr)/sizeof(int));
当传递使用以下内容创建的数组时,输入数组int size_arr[7]
适用于我的Quicksort和插入排序实现:
for(int k = 0; k < size; k++){
double sort_arr[size_arr[k]];
for(unsigned int l = 0; l < (sizeof(sort_arr)/sizeof(double)); l++){
sort_arr[l] = random_double(100.00, 1000.00);
}
}
使用此处生成的double值:
double random_double(double min, double max){
return (max - min) * ((double)rand() / (double)RAND_MAX) + min;
}
但是,当我通过合并排序函数运行数组时:
//merge sort algorithm
void merge_sort(double *A, int p, int r){
if(p < r){ //stopping condition
int mid = floor((p + r) / 2); //find array midpoint
merge_sort(A, p, mid); //recursively divide array
merge_sort(A, mid+1, r);
// merge(A, p, mid, r); //merge (sort) sub-arrays
merge_sort_merge(A, p, mid, r);
}
}
void merge_sort_merge(double *A, int left, int mid, int right){
double tmp[right];
int l = left, m = mid+1, sort_index = left;
for(int i = left; i <= right; i++){
tmp[i] = A[i];
}
while(l <= mid && m <= right){
if(tmp[l] <= tmp[m]){
A[sort_index] = tmp[l];
l++;
}else{
A[sort_index] = tmp[m];
m++;
}
sort_index++;
}
while(l <= mid){
A[sort_index] = tmp[l];
sort_index++;
l++;
}
}
当输入大小正好是129992时(我已经使用int size_arr[6]
测试它),它会崩溃。
完整代码如下:
#include <iostream>
#include <array>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <exception>
void merge_sort(double *A, int p, int r);
void merge(double *A, int p, int q, int r);
double random_double(double min, double max);
int main(){
srand(time(NULL)); //initialize random num generator with time(NULL) as seed
int size_arr[7] = {1000, 10000, 25000, 50000, 100000, 150000, 200000};
// int size_arr[6] = {1000, 10000, 25000, 50000, 100000, 129992};
int size = (sizeof(size_arr)/sizeof(int));
std::cout << "Merge Sort:" << std::endl;
for(int k = 0; k < size; k++){
double sort_arr[size_arr[k]];
for(unsigned int l = 0; l < (sizeof(sort_arr)/sizeof(double)); l++){
sort_arr[l] = random_double(100.00, 1000.00);
}
clock_t begin = clock();
try{
merge_sort(sort_arr, 0, (sizeof(sort_arr)/sizeof(double)));
}catch(const std::runtime_error& re){
std::cerr << "Runtime error: " << re.what() << std::endl;
}catch(const std::exception &exc){
std::cerr << exc.what();
}catch(...){
std::cerr << "Fuck" << std::endl;
}
clock_t end = clock();
std::cout << "n = " << size_arr[k] << '\t' << (end - begin) << std::endl;
}
return 0;
}
//merge sort algorithm
void merge_sort(double *A, int p, int r){
if(p < r){ //stopping condition
int mid = floor((p + r) / 2); //find array midpoint
merge_sort(A, p, mid); //recursively divide array
merge_sort(A, mid+1, r);
// merge(A, p, mid, r); //merge (sort) sub-arrays
merge_sort_merge(A, p, mid, r);
}
}
void merge_sort_merge(double *A, int left, int mid, int right){
double tmp[right];
int l = left, m = mid+1, sort_index = left;
for(int i = left; i <= right; i++){
tmp[i] = A[i];
}
while(l <= mid && m <= right){
if(tmp[l] <= tmp[m]){
A[sort_index] = tmp[l];
l++;
}else{
A[sort_index] = tmp[m];
m++;
}
sort_index++;
}
while(l <= mid){
A[sort_index] = tmp[l];
sort_index++;
l++;
}
}
double random_double(double min, double max){
return (max - min) * ((double)rand() / (double)RAND_MAX) + min;
}
我已尝试捕获异常(它没有抛出任何异常),使用VS JIT调试器但无法从中获取任何有用信息,反汇编如下(箭头指向错误):
00000000004100D0 cmp rax,1000h
00000000004100D6 ja 00000000004100BF
00000000004100D8 sub rcx,rax
00000000004100DB or qword ptr [rcx],0 <----
00000000004100DF pop rax
00000000004100E0 pop rcx
似乎无法单步执行&gt; 129k递归,当我有如此大的输入大小时,如何缩小问题所在?
感谢任何帮助
答案 0 :(得分:2)
当size_arr[k] == 129'992
时,
double sort_arr[size_arr[k]];
是129'992 * sizeof(double) == 129'992 * 8 == 1'039'936
。这只是1'048'576 == 1M
(二进制Mega)的羞怯。
C标准没有说明存储variable length arrays的位置(C ++根本没有定义VLA),但通常它们是在堆栈上分配的。
使用VS JIT
意味着您使用的是Windows。 Windows上的默认堆栈大小为1MB。 sort_arr
未使用的8640字节很容易被您的其他程序耗尽(主要是tmp
merge_sort_merge
sort_arr
,其中std::vector
的大小为spark-shell \
spark.driver.extraClassPath="/path/to/jar/spark-csv_2.11.jar" \
spark.executor.extraClassPath="spark-csv_2.11.jar"
。换句话说,你溢出了堆栈。
解决方案:不要将可变长度数组用于大型数组。 (如果您更喜欢便携式和标准兼容的程序,请不要使用VLA)。而是使用动态分配的数组(--jars
)。