我正在探索优化后续代码的方法。
代码循环遍历字符串。对于ith
字符串中的字符,
代码增加了2D数组中的一个条目
列。第i列的确切条目
增量取决于字符串中第i个字符的值;
字符串字母表中的每个字母都有一行。
通过循环遍历多个字符串并递增相同的2d数组(count
),
为字符串计算每个字符的出现次数。
代码如下:
string read = getReadFromData();
vector< vector<int> > count(4,vector<int>(read.size(),0));
for (int i = 0; i < read.size(); i++) {
switch(read[i]) {
case 'A': count[0][i]++; break;
case 'T': count[1][i]++; break;
case 'C': count[2][i]++; break;
case 'G': count[3][i]++; break;
}
我的优化尝试是使用1d数组 一个2d数组;旨在避免缓存未命中,如果字符串数据本身 在记忆中并不连续。 不幸的是,它没有减少计算时间;它们大致相同。
string read = getReadFromData();
int width = read.size()
vector<int> count(4*width,0);
for (int i = 0; i < width; i++) {
switch(read[i]) {
case 'A': count[ i]++; break;
case 'T': count[ width + i]++; break;
case 'C': count[2 * width + i]++; break;
case 'G': count[3 * width + i]++; break;
}
有人对如何优化此问题有任何建议吗? 切换行和列?或者改变增量的间隔? 谢谢你的建议。
更新:优化
所以,我认为主要问题是:
1)输入的不可预测性;在任何一个访问的内存位置 2D或1D版本取决于输入字符。 2)在一维示例中,相应位置之间的距离相距很远。此外,在2D中,但我正在优化一维示例。
在上面的一维例子中,i+1
的潜在位置相距很远; i+1
,i+1 + width
,i+1 + 2*width
,i+1 + 3*width
。我认为访问的不可预测性,加上距i+1
的距离很远,导致缓存未命中 - 我会在某些时候缓存。
优化的目的是减少到i+1
访问的距离。
为此,我交错了A,T,G,C计数,以便i+1
元素
距离最多7个条目;距离小得多。
string read = getReadFromData();
int width = read.size()
vector<int> count(4*width,0);
for (int i = 0; i < width; i++) {
switch(read[i]) {
case 'A': count[i*4 ]++; break;
case 'T': count[i*4 + 1]++; break;
case 'C': count[i*4 + 2]++; break;
case 'G': count[i*4 + 3]++; break;
}
我得到一个&gt;现在加速5倍,很好吃。
答案 0 :(得分:0)
一个想法是将数组预先计算为指针:
注意:未经测试的代码如下
vector< vector<int> > count(4,vector<int>(read.size(),0));
std::vector<int> * const p_a_counts = &count[0];
std::vector<int> * const p_t_counts = &count[1];
std::vector<int> * const p_c_counts = &count[2];
std::vector<int> * const p_g_counts = &count[3];
for (int i = 0; i < read.size(); i++) {
switch(read[i]) {
case 'A': p_a_counts->[i]++; break;
case 'T': p_t_counts->[i]++; break;
case 'C': p_c_counts->[i]++; break;
case 'G': p_g_counts->[i]++; break;
}
这个想法是减少各种数组的计算。
注意:您的代码看起来不正确。如果读取的第二个字母是'T',则第二个位置递增,而不是第一个。虽然你可以计算'T'在第二位置的次数。
编辑1:不同的视角
处理器更喜欢访问相同的数据区域,换句话说就是使用它们的数据缓存。
因此,将透视更改为数据视点:
string read = getReadFromData();
vector< vector<int> > count(4,vector<int>(read.size(),0));
for (int i = 0; i < read.size(); i++)
{
if (read[i] == 'A')
{
count[0][i]++;
}
}
for (int i = 0; i < read.size(); i++)
{
if (read[i] == 'T')
{
count[1][i]++;
}
}
for (int i = 0; i < read.size(); i++)
{
if (read[i] == 'C')
{
count[2][i]++;
}
}
for (int i = 0; i < read.size(); i++)
{
if (read[i] == 'G')
{
count[3][i]++;
}
}
以上内容应将count
数组保留在数据缓存中以用于不同目的。
答案 1 :(得分:0)
正如Thomas Matthews在他的评论中建议使用不同的数据结构,通常标准库给定的数据结构比你想要的慢。尝试只使用常规数组
int *count = new int [4 * width];