# what is the difference between assigning with and without range?

2 views (last 30 days)
Ernst Reißner on 23 Jul 2021
Commented: Chunru on 25 Jul 2021
I have variables a and b both holding columns with same length N.
Is there a difference between assigning
a=b
and
a(1:N)=b
?
Maybe there is a difference in performance??
a is preassigned with zeros(N, 1, 'double')
##### 2 CommentsShowHide 1 older comment
Chunru on 23 Jul 2021
I think matlab array object has the numel property (or something similar). So the overhead of getting numel is really minimal and one should not worry about it.

John D'Errico on 23 Jul 2021
Yes. There is a difference, and a fundamental one. In the first case, the assignment a=b COMPLETELY replaces a. The variable is overwritten, if it already exists. If not, a new variable is created with that name. What a was before is completely irrelevant. Even the class of a is replaced. For example:
a = uint8(1:3);
b = rand(1,4);
whos a b
Name Size Bytes Class Attributes a 1x3 3 uint8 b 1x4 32 double
As you can see, the two variables are not even the same classes. But now when we use a = b, a has been replaced. It has a new size. And a is now double precision.
a = b
a = 1×4
0.0366 0.9518 0.5077 0.6811
whos a b
Name Size Bytes Class Attributes a 1x4 32 double b 1x4 32 double
Now, lets try the second example, where we use indexing.
a = uint8(1:3)
a = 1×3
1 2 3
b = rand(1,4)
b = 1×4
0.3677 0.6780 0.7891 0.8548
Now use indexing:
a(1:4) = b
a = 1×4
0 1 1 1
whos a b
Name Size Bytes Class Attributes a 1x4 4 uint8 b 1x4 32 double
Here, elements of a are now selectively replaced with elements of b. But now there is a class conversion that happens first. Here the elements of a are still uint8, so a round was performed to convert elements of b into elements of a.
Is one operation faster than the other? The index operation must certainly be slower. But this is not a slow thing. So I'll put the operations into a function, then use timeit.
a = ones(1,3e7,'uint8');
b = rand(1,3e7);
timeit(@() speedtest1(a,b))
ans = 1.1380e-05
timeit(@() speedtest2(a,b))
ans = 0.2106
So, where there was a class conversion, speedtest1 is way faster. In the next test, there will be no class conversion.
a = randn(1,3e7);
b = rand(1,3e7);
timeit(@() speedtest1(a,b))
ans = 4.5789e-06
timeit(@() speedtest2(a,b))
ans = 0.2247
So here the replacement was way faster. In both cases, when you do an insert of selected elements, MATLAB spends a lot of time, first, generating the index vector. Then it needs to overwrite those selected elements, making sure any class conversion is done if needed.
function a = speedtest1(a,b)
a = b;
end
function a = speedtest2(a,b)
a(1:numel(b)) = b;
end
So, is there a difference? Yes. There must be one.
Chunru on 25 Jul 2021
If I were the one to implement the indexing such as a(2:2:1000) internally, I would prefere to not generationg the index 2:2:1000. Instead, I would using something similar to python iterator to generate those index when necessary (without taking up large size of memory). My bet is that MATLAB would not generate index vector explicitly here.
a = randn(1,1e6);
timeit(@() indexing1(a))
ans = 0.0012
timeit(@() indexing2(a))
ans = 0.0031
It shows that a(1:5e5) is faster, indicating indexing is likely imlicitly generated.
For the code like
A(1:100000) = X;
B(1:100000) = Y;
I guess there is no good reason we need to share 1:10000 if they have never been generated explicitly.
For subsref() and subsasgn(), they are designed for quite diffent purpose and we don't know matlab can manage those index generation in an implicit way.
function indexing1(a)
a(1:5e5) = 1;
end
function indexing2(a)
ind = 1:5e5;
a(ind) = 1;
end

Chunru on 23 Jul 2021
There should not be major performance difference between "a=b" and "a(1:N)=b". The assignment with range allow partial assignment of an array, for example:
a = zeros(100, 1);
b = randn(20, 1);
a(1:20) = b;
##### 2 CommentsShowHide 1 older comment
Chunru on 23 Jul 2021
@John D'Errico See my example below. I have explained the performance difference. The timeit for just create a pointer may not truly reflecting the difference. The factor of 10000 to 1 is not a fair comparison in the term I have explained below. I agree that type conversion will take more time (I have not thourt that from the question and assume same type here).