Perhaps the code is:
for (unsigned int i = 0; i < num_items; i++)
{
member_a[i] = some_value(i);
member_b[i] = something + some_other_value(i);
member_c[i] = member_a[i] + member_b[i];
}
The "optimization" of packing loops full of functionality is not necessarily a true optimization. The notion that loops are expensive is an old one, dating back to the mainframe era (when it was true). Since that time, we have designed faster processors, create more capable instruction sets, and improved compilers.
Packing loops full of instructions has a cost: the code is more complex. Being more complex, it is harder to read. (My example is simple, of course. Real code is more complicated. But I think the idea holds.)
I change this (admittedly simple) single loop to a set of smaller loops:
for (unsigned int i = 0; i < num_items; i++)
{
member_a[i] = some_value(i);
}
for (unsigned int i = 0; i < num_items; i++)
{
member_b[i] = something + some_other_value(i);
}
for (unsigned int i = 0; i < num_items; i++)
{
member_c[i] = member_a[i] + member_b[i];
}
The revised code looks longer (and to some, terribly inefficient) but look again. Each loop is simple and can be easily understood. Each loop performs one task, and one task only.
Moreover, languages that support vector operations (and there are a few such languages) can see their code simplified further:
for (unsigned int i = 0; i < num_items; i++)
{
member_a[i] = some_value(i);
}
for (unsigned int i = 0; i < num_items; i++)
{
member_b[i] = something + some_other_value(i);
}
member_c = member_a + member_b;
{
member_a[i] = some_value(i);
}
for (unsigned int i = 0; i < num_items; i++)
{
member_b[i] = something + some_other_value(i);
}
member_c = member_a + member_b;
Using smaller loops isolates the steps in the loop. The smaller loops can be optimized independently.
If the functions 'some_value()' and 'some_other_value()' can be changed to return vectors of values, the code can be simplified further:
member_a = some_values();
member_b = something + some_other_values();
member_c = member_a + member_b;
member_b = something + some_other_values();
member_c = member_a + member_b;
Doesn't that look simpler than the earlier versions of the code?
Languages without vector operations can approach the brevity of vector operations. Assuming an object-oriented language (without operator overloading), one could write:
member_a = some_values();
member_b = Numbers.Add(something, some_other_values());
member_c = Numbers.Add(member_a, member_b);
member_b = Numbers.Add(something, some_other_values());
member_c = Numbers.Add(member_a, member_b);
Assuming you had the functions:
double[] Numbers.Add(double value, double[] values);
double[] Numbers.Add(double[] values1, double[] values2);
and these functions are not that hard to write.
Code can be complex, sometimes because we think we are "helping" the computer. It's often better to help ourselves, to write programs that are simple and easy to understand.
No comments:
Post a Comment