J'essaie d'écrire une fonction pour convertir une image en caractères et couleurs pour la console Windows. Pour le moment, le calcul prend environ 13 secondes avec une image de 700x700 pixels mais ce temps n'est pas souhaitable surtout quand je prévois de rendre la fonction plus complexe afin de prendre en compte les formes de caractères.Comment accélérer l'exécution d'un calcul chronophage
Quelles sont les méthodes pour accélérer les calculs lourds et les boucles comme ci-dessous en C++? J'ai été recommandé plusieurs threads, SIMD, et inline assembly mais comment pourrais-je améliorer une fonction comme ci-dessous avec ces méthodes?
Ceci est le code que j'utilise actuellement.
unsigned char characterValues[256] = { 0 };
// This operation can be done ahead of time when the program is started up
{
ResourceInputStream in = ResourceInputStream();
// This image is the font for the console. The background color is black while the foreground color is white
in.open(BMP_FONT, 2); // 2 is for RT_BITMAP, BMP_FONT is a resource
if (in.isOpen()) {
auto bmp = readBitmap(&in, true);
in.close();
for (int x = 0; x < bmp->size.x; x++) {
for (int y = 0; y < bmp->size.y; y++) {
int charIndex = (x/8) + (y/12) * 16;
if (bmp->pixels[x][y].r == 255)
characterValues[charIndex]++;
}
}
}
}
// This operation is for asciifying the image
{
FileInputStream in = FileInputStream();
in.open(R"(image-path.bmp)");
if (in.isOpen()) {
auto bmp = readBitmap(&in, false);
in.close();
auto image = /* make default image here */
Point2I imageSize = (Point2I)GMath::ceil((Point2F)bmp->size/Point2F(8.0f, 12.0f));
int totalImageSize = imageSize.x * imageSize.y;
image->resize(imageSize);
auto palette = /* get palette of 16 colors here */
// Iterate through each (character area)
for (int imgx = 0; imgx < imageSize.x; imgx++) {
for (int imgy = 0; imgy < imageSize.y; imgy++) {
// Read image color value
int r = 0, g = 0, b = 0;
int totalRead = 0;
// Read each pixel inside the bounds of a single character
for (int px = 0; px < 8; px++) {
for (int py = 0; py < 12; py++) {
Point2I p = Point2I(imgx * 8 + px, imgy * 12 + py);
if (p < bmp->size) {
r += bmp->pixels[p.x][p.y].r;
g += bmp->pixels[p.x][p.y].g;
b += bmp->pixels[p.x][p.y].b;
totalRead++;
}
}
}
Color imageValue = Color(r/totalRead, g/totalRead, b/totalRead);
// A combo of a character and foreground/background color
Pixel closestPixel = Pixel();
float closestScore = std::numeric_limits<float>().max();
for (int col = 1; col < 255; col++) {
unsigned char f = getFColor(col);
unsigned char b = getBColor(col);
for (int ch = 1; ch < 255; ch++) {
// Calculate values
Color value = Color(
(palette[f].r * characterValues[ch] + palette[b].r * (TOTAL_CHARACTER_VALUE - characterValues[ch]))/TOTAL_CHARACTER_VALUE,
(palette[f].g * characterValues[ch] + palette[b].g * (TOTAL_CHARACTER_VALUE - characterValues[ch]))/TOTAL_CHARACTER_VALUE,
(palette[f].b * characterValues[ch] + palette[b].b * (TOTAL_CHARACTER_VALUE - characterValues[ch]))/TOTAL_CHARACTER_VALUE
);
// Add up score here
float score =
(float)((int)value.r - (int)imageValue.r) * (float)((int)value.r - (int)imageValue.r) +
(float)((int)value.g - (int)imageValue.g) * (float)((int)value.g - (int)imageValue.g) +
(float)((int)value.b - (int)imageValue.b) * (float)((int)value.b - (int)imageValue.b);
if (score < closestScore) {
closestPixel = Pixel((unsigned char)ch, (unsigned char)col);
closestScore = score;
}
}
}
// Set the character/color combo here
}
}
}
}
Cela appartient à [codereview.se] si vous avez un code fonctionnel et que vous cherchez à l'améliorer. –
@John Coleman Merci, je vais le déplacer là maintenant –
Avez-vous essayé de compiler avec le drapeau d'optimisation -O3? Je ne tenterais pas le code avant de laisser gcc tenter de l'améliorer d'abord. – ScottK