回复 44# 老刘1号
这个牛跌前面楼层有提到过呀。
我们主要在折腾大数字和浮点数。如果只在signed int范围内开整数根,早就可以结帖了。
小程说他要写一个版本的时候我以为“硬核”要来了,结果 …… 
那本《MCA》非常硬核!打算用C艹实践其中一小部分算法(大部分看不懂,小部分似懂非懂)。
回复 43# SQYSQYSQY
批处理的“数组”属于伪数组,和其他语言的数组有本质的区别,因为批的“索引”不只是数字,还有字母和符号,变量长度亦不确定,这和其他语言的哈希表(hash table)相似。
在C/C++里面的数组操作不需要“搜索”,可直接通过计算偏移量取内存地址,因为定长的数组在初始化后占用一段连续内存空间,且每个单元占用相同字节,
给定一个编号,通过 编号*字节大小+起点地址 可得目标内存地址,直接存取。
C++ vector容器的 [] 操作符消耗占用高,和其独立的实现有关(可能做了各种判断和转换处理),换用更纯粹的C语言数组可以减少这种消耗。
实测,元素数量为80W的容器/数组,1000次遍历每一个元素并写入int值,- #include <iostream>
- #include <vector>
- #include <chrono>
- using namespace std;
- using namespace std::chrono;
-
- const int SIZE = 800000;
- void vec_test(void);
- void c_array_test(void);
- void c_pointer_test(void);
- void time_used(system_clock::time_point& time_a);
-
- vector<int> vec(SIZE);
- int array1[SIZE];
- int array2[SIZE];
-
- int main(int argc, char *argv[])
- {
- system_clock::time_point start = system_clock::now();
- for (int i = 0; i < 1000; i++) vec_test();
- time_used(start);
-
- for (int i = 0; i < 1000; i++) c_array_test();
- time_used(start);
-
- for (int i = 0; i < 1000; i++) c_pointer_test();
- time_used(start);
- return 0;
- }
-
- void vec_test(void) {
- register int it;
- for (it = 0; it < SIZE; it++) vec[it] = it;
- }
-
- void c_array_test(void) {
- register int it;
- for (it = 0; it < SIZE; it++) array1[it] = it;
- }
-
- void c_pointer_test(void) {
- register int it;
- register int *pt = array2;
- for (it = 0; it < SIZE; it++) *(pt + it) = it;
- }
-
- void time_used(system_clock::time_point& time_a) {
- duration<double> diff;
- diff = chrono::system_clock::now() - time_a;
- cout << "Time used: " << diff.count() << endl;
- time_a = chrono::system_clock::now();
- }
复制代码 g++编译测试结果:
Time used: 1.24807
Time used: 0.400023
Time used: 0.393022
Visual Studio编译,差距更明显
Time used: 3.92722
Time used: 0.0410024
Time used: 0.0360021
如果一定要用 vector 又不想用它的 [] ,可以申请一个指针,int *vp = vec.data()
通过*vp指针直接算地址读写内存,速度和c_array一样快,想要更快,申请一个寄存器指针 register int *vp。
这就是自由度,可定制,可接管。
讨论算法,可以不分语言。谈论模块化思想,也可以不分语言,用批处理同样可以表达。
但要说极限压榨性能,怎么也轮不到批处理。 |