C и Matlab: Почему эта строка в Matlab становится таким количеством строк в коде C ++, сгенерированном Matlab Coder?

У меня есть код Matlab, который запускается много миллионов раз, как упоминалось в этом вопросе: Matlab: многократный вызов одной и той же mex-функции из цикла вызывает слишком много накладных расходов?

Я пытаюсь исправить это, чтобы увидеть, помогает ли это. Теперь, когда я генерирую код из кода Matlab с помощью инструмента Matlab Coder, код, как правило, является разумным, но эта одна строка кода Matlab (в комментарии к C ++ в первой строке ниже) порождает это чудовище, и я понятия не имею, почему. Любая помощь в понимании и уменьшении его сложности будет принята с благодарностью.

Для контекста, d — это двумерная матрица, а s1 — это вектор строки. s1_idx назначается равным length (s1) + 1 в предыдущем коде C ++,

/* d(:, 1) = 0:length(s1); */
cdiff = s1_idx_0 - 1;
for (nm1d2 = 0; nm1d2 <= cdiff; nm1d2++) {
tmp_data[nm1d2] = nm1d2;
}
ndbl = (int32_T)muDoubleScalarFloor((real_T)s1_sizes[1] + 0.5);
apnd = ndbl;
cdiff = ndbl - s1_sizes[1];
if (muDoubleScalarAbs((real_T)cdiff) < 4.4408920985006262E-16 * (real_T)s1_sizes[1]) {
ndbl++;
apnd = s1_sizes[1];
} else if (cdiff > 0) {
apnd = ndbl - 1;
} else {
ndbl++;
}
if (ndbl > 0) {
b_tmp_data[0] = 0.0;
if (ndbl > 1) {
b_tmp_data[ndbl - 1] = (real_T)apnd;
nm1 = ndbl - 1;
nm1d2 = nm1;
nm1d2 = (int32_T)((uint32_T)nm1d2 >> 1);
for (cdiff = 1; cdiff <= nm1d2 - 1; cdiff++) {
b_tmp_data[cdiff] = (real_T)cdiff;
b_tmp_data[(ndbl - cdiff) - 1] = (real_T)(apnd - cdiff);
}
if (nm1d2 << 1 == nm1) {
b_tmp_data[nm1d2] = (real_T)apnd / 2.0;
} else {
b_tmp_data[nm1d2] = (real_T)nm1d2;
b_tmp_data[nm1d2 + 1] = (real_T)(apnd - nm1d2);
}
}
}
cdiff = s1_idx_0 - 1;
for (nm1d2 = 0; nm1d2 <= cdiff; nm1d2++) {
SD->f0.d_data[tmp_data[nm1d2]] = b_tmp_data[nm1d2];
}

7

Решение

Это довольно забавный сгенерированный код для того, чего вы действительно хотите достичь. Вы просто хотите вставить целые числа от 0 до k в массив. Но генератор кода построен для общего случая. Итак, сгенерированный код состоит из трех частей:

  1. Создайте массив индексов, указывающих, куда с левой стороны попадут элементы с правой стороны. Вы использовали : выражение, но вы могли бы использовать что-то еще. Генератор кода должен быть готов к тому, что вы делаете что-то вроде d(length(s1):0, 1)=0:length(s1),
  2. Создайте массив значений для правой части. Вы просто делаете последовательные целые числа, но генератор кода готов справиться с двойными числами, и при создании значений из диапазона двойных чисел у вас могут возникнуть смешные проблемы округления. Он проверяет все виды крайних случаев.
  3. Наконец, есть цикл, который фактически присваивает значения с правой стороны слотам памяти с левой стороны, как проиндексировано массивом, созданным на шаге 1.

В конце концов, может быть, все, что вам нужно, это:

cdiff = s1_idx_0 - 1;
for (nm1d2 = 0; nm1d2 <= cdiff; nm1d2++) {
SD->f0.d_data[nm1d2] = nm1d2;
}
4

Другие решения

MatLab — это особый случай, предназначенный для работы со специальными математическими функциями. Вы понимаете, что под капотом все еще переводится много машинного кода, который процессор может понять.

Есть много вопросов по SO, которые задают одно и то же: «почему XX так легко сделать в Matlab и так сложно в C ++?». Потому что Матлаб был предназначенный для этого пока C ++ является языком общего назначения.

Разработчики Matlab должны были написать эти большие листы кода, чтобы предоставить вам возможность использовать эту функциональность всего одной строкой. C ++ не имеет его в стандартной библиотеке, поэтому вам нужно будет сделать это самостоятельно.

Ну, возьми простой пример. Предположим, пользователи A и B хотят решить квадратичное уравнение. Пользователь А использует математический пакет, и все, что ему нужно сделать, это написать

НАЙТИ x В 2x2 + 6x + 3 = 0

Пользователь B, с другой стороны, использует C ++, и он должен записывать функция для подсчета дискриминанта, вычисления значений (ему, конечно, придется беспокоиться и об отрицательном дискриминанте) и вывода их, что разработчики математического пакета уже сделали для пользователя A. Это действительно много кода , вот пример, который я быстро погуглил.

А теперь представьте, что пользователь А говорит: «Эй, Б, зачем, черт возьми, тебе нужно писать столько кода? Я могу сделать это всего за 1 строку!» и это будет твой случай;)

Также не забывайте, что автоматически сгенерированный код не всегда лучший код, если вы говорите о читабельности и простоте понимания человеком.

2

Я опаздываю на эту вечеринку, но существующие ответы сосредоточены на том, почему это произошло, и не обсуждают, что вы можете с этим поделать.

Если вы знаете, какая строка вызывает этот странный, грязно выглядящий C-код, попробуйте изменить эту строку. Вместо:

d(:, 1) = 0:length(s1);

Одна вещь, чтобы попробовать это удалить зависимость от переменной s1:

d(:, 1) = 0:size(d,1);

Другой вариант — написать простой цикл, который можно почти напрямую перевести на C. Надеемся, что codegen даст очень похожий и простой C-код.

for i = 0:size(d,1)
d(i,1) = i;
end
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector