简体   繁体   English

C和Matlab:为什么Matlab中的这一行在Matlab Coder生成的C ++代码中变得如此之多?

[英]C and Matlab: Why does this one line in Matlab become so many lines in C++ code generated by Matlab Coder?

I have some Matlab code that is run many millions of times as mentioned in this question: Matlab: Does calling the same mex function repeatedly from a loop incur too much overhead? 我有一些运行数百万次的Matlab代码,如本问题所述: Matlab:从循环中重复调用相同的mex函数会产生太多的开销吗?

I'm trying to mex-ify it to see whether that helps. 我正在尝试mex-ify,看看是否有帮助。 Now, when I generate code from the Matlab code using Matlab Coder tool, the code is generally reasonable, but this one line of Matlab code (in a C++ comment in the first line below) begets this monstrosity, and I have no idea why. 现在,当我使用Matlab Coder工具从Matlab代码生成代码时,代码通常是合理的,但是这一行Matlab代码(在下面第一行的C ++注释中)会产生这种怪异,我不知道为什么。 Any help in understanding and reducing its complexity would be appreciated. 任何帮助理解和降低其复杂性将不胜感激。

For context, d is a two dimensional matrix, and s1 is a row vector. 对于上下文,d是二维矩阵,s1是行向量。 s1_idx is assigned to be length(s1) + 1 in preceding C++ code, 在前面的C ++代码中,s1_idx被指定为长度(s1)+ 1,

/* 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];
}

That's pretty funny generated code for what you actually want to accomplish. 对于你真正想要实现的目标,这是非常有趣的生成代码。 You just want to stuff the integers 0 to k into an array. 您只想将整数0到k填充到数组中。 But the code generator is built to deal with the general case. 但是代码生成器是为了处理一般情况而构建的。 So there are three parts to the generated code: 所以生成的代码有三个部分:

  1. Create an array of indices specifying where, on the left-hand side, the elements from the right-hand side will go. 创建一个索引数组,指定左侧的元素从右侧开始的位置。 You used the : expression, but you could have used something else. 你使用了: expression,但是你可以使用其他东西。 The code generator has to be prepared for you doing something like d(length(s1):0, 1)=0:length(s1) . 代码生成器必须为你准备像d(length(s1):0, 1)=0:length(s1)
  2. Create an array of values for the right-hand side. 为右侧创建一个值数组。 Your just doing sequential integers, but the code generator is prepared to deal with doubles and when creating values from a range of doubles you might have funny rounding issues. 你只是做顺序整数,但代码生成器准备处理双打,当从一系列双打创建值时,你可能会有有趣的舍入问题。 It's checking for all kinds of edge cases. 它正在检查各种边缘情况。
  3. Finally, there's the loop that actually assigns the values on the right-hand side to memory slots on the left-hand side as indexed by the array created in step 1. 最后,有一个循环实际上将右侧的值分配给左侧的内存插槽,由步骤1中创建的数组索引。

In the end, it might be that all you need is: 最后,您可能只需要:

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

MatLab is a special case, designed to work with special math functions. MatLab是一个特殊的案例,旨在使用特殊的数学函数。 You do realize that under the hood stuff is still being translated to lots of machine code which processor can understand. 你确实意识到,引擎盖下的东西仍然被翻译成许多处理器可以理解的机器代码。

There are a lot of questions on SO that ask the same thing: "why is XX so easy to do in Matlab and so hard in C++?". 在SO上有很多问题要求同样的事情:“为什么XX在Matlab中很容易做到,在C ++中如此难以实现?”。 Because Matlab was designed for this while C++ is a general-purpose language. 因为Matlab是为此而设计的 ,而C ++是一种通用语言。

Matlab developers had to write those big code sheets to provide you a way to use this functionality with just one line. Matlab开发人员必须编写这些大型代码表,以便为您提供仅使用一行的方法来使用此功能。 C++ doesn't have it in the standard library, thus you will need to make it yourself. C ++在标准库中没有它,因此您需要自己创建它。

Well, take a simple example. 好吧,举一个简单的例子。 Assume users A and B want to solve a quadratic equasion. 假设用户A和B想要求解二次方。 User A is using a mathematical package, and all he has to do is write 用户A正在使用数学包,他所要做的就是写

FIND x IN 2x 2 + 6x + 3 = 0 FIND x IN 2x 2 + 6x + 3 = 0

User B, on the other hand, is using C++, and he has to write a function to count the discriminant, compute the values (he'll have to worry about negative discriminant too of course) and output them, something that the developers of the mathematical package had already done for user A. That is a lot of code really, here's an example that I quickly googled. 另一方面,用户B正在使用C ++,他必须编写一个函数来计算判别式,计算值(他当然也要担心负判别)并输出它们,这是开发人员的事情。数学包已经为用户A完成了。这真的是很多代码, 是我快速搜索一个例子。

Now imagine user A saying "Hey, B, why the hell do you need to write so much code? I can do it in just 1 line!" 现在假设用户A说“嘿,B,你为什么要编写这么多代码呢?我只能在一行中做到这一点!” and this will be your case ;) 这将是你的情况;)

Also don't forget that automatically-generated code is not always the best code ever if you talk about readability and ease of understanding by human. 另外不要忘记,如果你谈论人类可读性和易于理解的话,自动生成的代码并不总是最好的代码。

I'm late to this party, but the existing answers focus on why it happened and don't discuss what you can do about it. 我迟到了这个派对,但现有的答案集中在它为什么会发生,而不讨论你能做些什么。

If you know which line causes that strange, messy looking C code, you should try changing that line. 如果您知道哪一行会导致看起来很奇怪,看起来很乱的C代码,那么您应该尝试更改该行。 Instead of: 代替:

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

One thing to try is removing the dependency on variable s1 : 要尝试的一件事是删除对变量s1的依赖:

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

Another option is to write a simple loop that can be almost directly translated to C. Hopefully codegen will give very similar and simple C code. 另一种选择是编写一个几乎可以直接转换为C的简单循环。希望codegen能够提供非常相似和简单的C代码。

for i = 0:size(d,1)
    d(i,1) = i;
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM