C++ vs Fortran: Como a ordem de memória afeta o desempenho de strings e arrays
Introdução
Ao escrever programas de alta performance em linguagens como C++ ou Fortran, muitos desenvolvedores negligenciam um detalhe crucial: a forma como as strings e arrays multidimensionais são armazenados e percorridos na memória. Esse fator, embora muitas vezes ignorado, pode impactar drasticamente a eficiência de cache e o desempenho computacional.
Neste artigo, vamos entender como strings e arrays são organizados na memória em C++ e Fortran, e como isso influencia na escolha de loops aninhados para máxima performance.
1. Strings em C e C++ são armazenadas como vetores linha
Na linguagem C e C++, strings são armazenadas como arrays unidimensionais de caracteres terminados por \0. No entanto, ao lidarmos com arrays bidimensionais de caracteres, como char nome[10][20], a memória é percorrida linha a linha (row-major order).
Ou seja:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 20; j++) {
nome[i][j] = 'a'; // percorre linha por linha
}
}Confirmação técnica: Em C/C++, arrays multidimensionais são armazenados em ordem de linha (row-major). Isso significa que nome[0][0], nome[0][1], …, nome[0][19] vêm antes de nome[1][0] na memória.
2. Strings e arrays em Fortran são armazenados como vetores coluna
Em Fortran, arrays e strings seguem uma abordagem diferente. Arrays multidimensionais, como:
character(len=1) :: nome(20,10)
São armazenados em ordem de coluna (column-major). Isso significa que o acesso sequencial mais eficiente ocorre percorrendo primeiro as colunas internas.
Exemplo:
do j = 1, 10
do i = 1, 20
nome(i, j) = 'a'
end do
end doCode language: JavaScript (javascript)
Confirmação técnica: Fortran armazena arrays em ordem de coluna (column-major order). Assim, nome(1,1), nome(2,1), …, nome(20,1) vêm antes de nome(1,2) na memória.
3. Acesso eficiente à memória: C++ vs Fortran
Ao usar arrays bidimensionais como int var[10][10] em C++, o acesso eficiente depende do padrão de armazenamento:
Melhor forma em C++ (row-major):
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
var[i][j] = i + j; // acesso sequencial de memória
}
}Pior forma em C++:
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 10; i++) {
var[i][j] = i + j; // salto entre linhas -> cache miss
}
}Melhor forma em Fortran (column-major):
integer :: var(10,10)
do j = 1, 10
do i = 1, 10
var(i,j) = i + j ! acesso sequencial na memória
end do
end doCode language: JavaScript (javascript)
Pior forma em Fortran:
do i = 1, 10
do j = 1, 10
var(i,j) = i + j ! salto entre colunas -> cache miss
end do
end doCode language: JavaScript (javascript)
Conclusão
A performance de um código não depende apenas dos algoritmos, mas também da organização da memória e da forma como os dados são acessados. Em linguagens como C++ e Fortran, entender a ordem de armazenamento de arrays (linha vs coluna) é fundamental para obter o máximo desempenho, especialmente em aplicações científicas e de engenharia.
