【发布时间】:2017-03-28 16:24:40
【问题描述】:
我正在尝试模拟很多 2 状态、3 符号(单向磁带)图灵机。每个模拟将有不同的输入,并将运行固定数量的步骤。该程序当前的瓶颈似乎是模拟器,它在不会停止的图灵机上占用了大量内存。
任务是模拟大约 650000 个 TM,每个 TM 有大约 200 个非空白输入。我尝试的最大步数是 10 亿 (10**9)。
下面是我正在运行的代码。 vector<vector<int> > TM 是一个转换表。
vector<int> fast_simulate(vector<vector<int> > TM, string TM_input, int steps) {
/* Return the state reached after supplied steps */
vector<int> tape = itotape(TM_input);
int head = 0;
int current_state = 0;
int halt_state = 2;
for(int i = 0; i < steps; i++){
// Read from tape
if(head >= tape.size()) {
tape.push_back(2);
}
int cell = tape[head];
int data = TM[current_state][cell]; // get transition for this state/input
int move = data % 2;
int write = (data % 10) % 3;
current_state = data / 10;
if(current_state == halt_state) {
// This highlights the last place that is written to in the tape
tape[head] = 4;
vector<int> res = shorten_tape(tape);
res.push_back(i+1);
return res;
}
// Write to tape
tape[head] = write;
// move head
if(move == 0) {
if(head != 0) {
head--;
}
} else {
head++;
}
}
vector<int> res {-1};
return res;
}
vector<int> itotape(string TM_input) {
vector<int> tape;
for(char &c : TM_input) {
tape.push_back(c - '0');
}
return tape;
}
vector<int> shorten_tape(vector<int> tape) {
/* Shorten the tape by removing unnecessary 2's (blanks) from the end of it.
*/
int i = tape.size()-1;
for(; i >= 0; --i) {
if(tape[i] != 2) {
tape.resize(i+1);
return tape;
}
}
return tape;
}
在性能或内存使用方面我有什么可以改进的地方吗?即使减少 2% 也会产生显着差异。
【问题讨论】:
-
您通过价值传递了一些潜在的巨大
vectors,因此,积极地复制它们。 -
另外,你不断地在
itotape中使用push_backing,从而每秒改变tape负载的大小,这是相当昂贵的。请注意,TM_input是一个字符串,您知道其大小,因此您可以一次分配足够的内存。 -
这个问题可能更适合codereview.stackexchange.com(前提是它是工作代码)。我不确定它是否归类为过于宽泛或基于意见,但可以肯定的是,其他人有同样问题的可能性很小
-
@ForceBru 好点,我可以通过引用传递磁带。我不知道磁带的最终大小,所以如果磁带在单词之后会立即增长,那么询问内存字符串的长度有什么意义吗?
-
@spyr03,
TM_input是一个std::string,它已经“知道”它的大小。我想说你已经知道itotape的大小,所以你可以一次为tape分配足够的内存,然后用数据填充它。目前你不断地通过连续分配内存来增加tape的大小,这会浪费很多时间。
标签: c++ performance performance-testing turing-machines