dispatch_apply gives incorrect output data - objective-c

I have two arrays: array1 and array2. Each object of arrays is an array too (2D arrays). In this way I multiple them. So how I have big arrays I use dispatch_apply. Every time i receive different results include a right result. Maybe somebody knows how to fix it?
dispatch_apply([array2 count], queue, ^(size_t j)
{
k = 0;
for (int l = 0; l < [[array1 objectAtIndex:0] count]; l++) {
k += [[[array1 objectAtIndex:i] objectAtIndex:l] intValue] *
[[[array2 objectAtIndex:j] objectAtIndex:l] intValue];
}
kNSNumber = [NSNumber numberWithInt:k];
[multipliedArrayInto replaceObjectAtIndex:j withObject:kNSNumber];
});
[resulArray insertObject:multipliedArrayInto atIndex:i];
}

There's two things, I can suggest, and I bet one of them (or both) is the overarching solution to your problem.
First, I would declare k local to the block, so there would be no question that you are overwriting it or not. You likely have the same problem with kNSNumber inside the block. If you are just using that NSNumber instance to slam into the multipliedArrayInto accumulator, you may as well remove kNSNumber, and use #(k) in it's place (if only to be more readable). Similarly, make sure multipliedArrayInto is declared just before the dispatch_apply, in what looks like an outer for loop (where ever i is coming from). And finally, make sure resulArray is instantiated, or otherwise readied just before that outer for loop.
Second, is queue a concurrent or serial queue? If you are using dispatch_apply like a parallel-executing for/enumeration -- which is likely, I think, so you are taking about handling "big arrays" efficiently -- then you are practically guaranteeing that k is being overwritten. If you change it to serial, it may work as designed. If you want it to be parallel, you will need to move the declaration of your k accumulator inside the block, and make sure the declaration of other variables makes sense, too.
Update to reflect question updates:
#antonytonies ideally, your followup answer on this thread should be moved into the question itself, so that people can follow this thread easier.
So, it looks like what I described is exactly your problem.
The global queues are all concurrent queues, which means that (hypothetically) all the dispatch blocks are executing at once, and the contents of k and other variables are getting blown away depending on how the order of the blocks executes.
I've taken your update (in the "answer" you added), and modified it to probably work:
// I renamed your method, because nameless parameters pain me. This is cosmetic, and doesn't
// matter for the problem at hand.
- (NSMutableArray *)multiplicationArrays:(NSMutableArray *)array vector:(NSMutableArray *)vector
{
// IMHO, you want to set resultArray to nil here. Another option is to set it to nil in the
// else case, below. Properties in Objective-C are initalized to nil,0,false,etc; you can
// rely on ARC to initialize pointer to objc objects on the stack, too. However, someone
// reading this code may or may not know that. IMHO, using the explicitly assignement makes it
// clear that you're going to be returning `nil` or an instance of `NSMutableArray`.
NSMutableArray *resultArray = nil;
if ([[array objectAtIndex:0] count] == [vector count]) {
// Nicely done w/ pre-allocating the result array here, so that there's no question
// of the indexes matches the results later on.
resultArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
for (int i=0; i < [array count]; i++) {
[resultArray insertObject:[NSNull null] atIndex:i];
}
// 'queue' here is a concurrent queue. This means that you are proclaiming to the runtime
// that the blocks being executed are able to operate correctly w/o interference from each
// other. This is also thought of in terms of parallel execution: all these blocks may run
// **at once**. This *also* means, that you must not share storage between them.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([array count], queue, ^(size_t j) {
// Moved 'result' inside the block.
NSInteger result = 0;
for (int l = 0; l < [[array objectAtIndex:0] count]; l++) {
// These array reads are **NOT** thread safe. They probably don't cause must trouble in
// practice, but you may want to reconfigure this.
result += [[[array objectAtIndex:j] objectAtIndex:l] intValue] * [[vector objectAtIndex:l] intValue];
}
// The replace of the object into resultArray is **NOT** thread-safe.
// This probably hasn't caused you much trouble, since you can guarantee that
// you aren't writing at the same index. However, I would strongly suggest to
// change this to be thread-safe.
[resultArray replaceObjectAtIndex:j withObject:#(result)];
});
}
else {
NSLog(#"matrix count isn't correspond");
}
return resultArray;
}
Finally: consider just using Apple's Accelerate framework for this sort of problem solving. It's available on OSX and iOS, so you should have all of your bases covered.

it's the same thing if I multiple 2D-array and vector
-(NSMutableArray*)multiplicationArraysWithVector:(NSMutableArray *)array :(NSMutableArray *)vector
{
NSMutableArray* resultArray;
if ([[array objectAtIndex:0] count] == [vector count])
{
resultArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
for (int i=0; i < [array count]; i++) {
[resultArray insertObject:[NSNull null] atIndex:i];
}
__block NSInteger result;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([array count], queue, ^(size_t j)
{
result = 0;
for (int l = 0; l < [[array objectAtIndex:0] count]; l++) {
result += [[[array objectAtIndex:j] objectAtIndex:l] intValue] * [[vector objectAtIndex:l]intValue];
}
[resultArray replaceObjectAtIndex:j withObject:#(result)];
});
}
else
{
NSLog(#"matrix count isn't correspond");
}
return resultArray;
}
In this case I can get a right or wrong data result.

Related

NSMutableArray was mutated while being enumerated

I have an array in an old objective-C app that I am using to learn more "complicated" coding. It is back from the old days of OS X and was very much broken. I have gotten it to work (mostly)! However, the app has an NSMutableArray of images, 7 in total. I use a random number generator to insert the images on the screen, some code to allow them to fall, and then, using screen bounds, when they reach "0" on the Y axis they are removed from the array.
I initially just had:
if( currentFrame.origin.y+currentFrame.size.height <= 0 )
{
[flakesArray removeObject:myItem];
I have read when removing objects from an array it is best practice to iterate in reverse...so I have this bit of code:
for (NSInteger i = myArray.count - 1; i >= 0; i--)
{ //added for for statement
if( currentFrame.origin.y+currentFrame.size.height <= 0 )
{
[myArray removeObjectAtIndex:i];
}
Sadly both methods result in the same mutated while enumerated error. Am I missing something obvious?
If I add an NSLog statement I can get, I think, the index of the item that needs to be removed:
NSLog (#"Shazam! %ld", (long)i);
2017-01-07 14:39:42.086667 MyApp[45995:7500033] Shazam! 2
I have looked through a lot and tried several different methods including this one, which looks to be the most popular with the same error.
Thank you in advance! I will happily provide any additional information!
Adding more:
Sorry guys I am not explicitly calling NSFastEnumeration but I have this:
- (void) drawRectCocoa:(NSRect)rect
{
NSEnumerator* flakesEnum = [flakesArray objectEnumerator];
then
for( i = 0; i < numberToCreate; i++ )
{
[self newObject:self];
}
while( oneFlake = [flakesEnum nextObject] )
It is here where:
if( currentFrame.origin.y+currentFrame.size.height <= 0 )
{
NSLog (#"Shazam! %i", oneFlake);
[flakesArray removeObject:oneFlake];
}
Thank you all. I am learning a lot from this discussion!
There are two ways to go: (1) collect the objects to remove then remove them with removeObjectsInArray:.
NSMutableArray *removeThese = [NSMutableArray array];
for (id item in myArray) {
if (/* item satisfies some condition for removal */) {
[removeThese addObject:item];
}
}
// the following (and any other method that mutates the array) must be done
// *outside of* the loop that enumerates the array
[myArray removeObjectsInArray:removeThese];
Alternatively, reverseObjectEnumeration is tolerant of removes during iteration...
for (id item in [myArray reverseObjectEnumerator]) {
if (/* item satisfies some condition for removal */) {
[myArray removeObject: item];
}
}
As per the error, you may not mutate any NSMutableArray (or any NSMutable... collection) while it is being enumerated as part of any fast enumeration loop (for (... in ...) { ... }).
#danh's answer works as well, but involves allocating a new array of elements. There are two simpler and more efficient ways to filter an array:
[array filterUsingPredicate:[NSPredicate predicateWithBlock:^(id element, NSDictionary<NSString *,id> *bindings) {
// if element should stay, return YES; if it should be removed, return NO
}];
or
NSMutableIndexSet *indicesToRemove = [NSMutableIndexSet new];
for (NSUInteger i = 0; i < array.count; i += 1) {
if (/* array[i] should be removed */) {
[indicesToRemove addIndex:i];
}
}
[array removeObjectsAtIndexes:indicesToRemove];
filterUsingPredicate: will likely be slightly faster (since it uses fast enumeration itself), but depending on the specific application, removeObjectsAtIndexes: may be more flexible.
No matter what, if you're using your array inside a fast enumeration loop, you will have to perform the modification outside of the loop. You can use filterUsingPredicate: to replace the loop altogether, or you can keep the loop and keep track of the indices of the elements you want to remove for later.

Calculating value of K without messages

Question:
Find the value of K in myInterViewArray without any messages/calls
I was given this hint:
The numbers in the array will never exceed 1-9.
NSArray *myInterViewArray = #[#2,#1,#3,#9,#9,#8,#7];
Example:
If you send 3, the array will return the 3 biggest values in myInterViewArray * 3. So in the example below, K = 9 + 9 + 8.
--
I was asked this question a while back in an interview and was completely stumped. The first solution that I could think of looked something like this:
Interview Test Array:
[self findingK:myInterViewArray abc:3];
-(int)findingK:(NSArray *)myArray abc:(int)k{ // With Reverse Object Enumerator
myArray = [[[myArray sortedArrayUsingSelector:#selector(compare:)] reverseObjectEnumerator] allObjects];
int tempA = 0;
for (int i = 0; i < k; i++) {
tempA += [[myArray objectAtIndex:i] intValue];
}
k = tempA;
return k;
}
But apparently that was a big no-no. They wanted me to find the value of K without using any messages. That means that I was unable to use sortedArrayUsingSelector and even reverseObjectEnumerator.
Now to the point!
I've been thinking about this for quite a while and I still can't think of an approach without messages. Does anyone have any ideas?
There is only one way to do that and that is bridging the array to CF type and then use plain C, e.g.:
NSArray *array = #[#1, #2, #3];
CFArrayRef cfArray = (__bridge CFArrayRef)(array);
NSLog(#"%#", CFArrayGetValueAtIndex(cfArray, 0));
However, if the value is a NSNumber, you will still need messages to access its numeric value.
Most likely the authors of the question didn't have a very good knowledge of the concept of messages. Maybe they thought that subscripting and property access were not messages or something else.
Using objects in Obj-C without messages is impossible. Every property access, every method call, every method initialization is done using messages.
Rereading the question, they probably wanted you to implement the algorithm without using library functions, e.g. sort (e.g. you could implement a K-heap and use that heap to find the K highest numbers in a for iteration).
I assume what is meant is that you can't mutate the original array. Otherwise, that restriction doesn't make sense.
Here's something that might work:
NSMutableArray *a = [NSMutableArray array];
for (NSNumber *num in array) {
BOOL shouldAdd = NO;
for (int i = a.count - 1; i >= k; i--) {
if ([a[i] intValue] < [num intValue]) {
shouldAdd = YES;
break;
}
}
if (shouldAdd) {
[a addObject:num];
}
}
int result = a[a.count - k];
for (int i = k; k < a.count; k++) {
result += [a[i] intValue];
}
return result;

Should I use mutableArray or mutableDictronary?

I'm trying to fill a muatableArray or mutableDictionary. I will then take out 1 object, say 4, then I will need all elements beyond 4 moved by subtracting 1 from their index.
This is easy to do in a mutableArray with removeObjectAtIndex. But the problem to that is, I will not be adding objects to every single index.
Here is the basic layout of what I mean:
1. one
2. two
3. three
// 4. (Empty)
5. five
6. six
// 7. (Empty)
// 8. (Empty)
9. nine
10. ten
So my question is, should I use a mutableaArray, and just add nulls to the empty indexs like this:
for (int i = 0 ; i < [myArray count]; i++)
{
if (![myArray objectAtIndex:i]) {
[array addObject:[NSNull null]];
}
}
Or should I use a mutableDictionary, and when I need to remove an object, I should just do it all manually like this:
[self.myDict removeObjectForKey:currentKey];
for (NSNumber *key in [[self.myDict allKeys] sortedArrayUsingSelector:#selector(compare:)]) {
if ([key integerValue] > currentKey) {
NSNumber *newKey = #([key integerValue]-1);
self.myDict[newKey] = self.myDict[key];
[self.myDict removeObjectForKey:key];
}
}
for (int i = 0 ; i < [myArray count]; i++)
{
if (![myArray objectAtIndex:i]) {
[array addObject:[NSNull null]];
}
}
First, you are not turning on all the warnings that you should turn on. As evidence I take that you are using int i and not NSUInteger i. This is a very bad habit. Turning on warnings is a very cheap and effective method to find programming errors.
Second, don't use ! to check whether a pointer is nil. Do the decent thing and compare it to nil. You want to check that it is nil, so that is what you should write in your code. Writing the code in a way that it reflects what you want to do is a very cheap and effective method to avoid programming errors.
Third, this code is absolutely pointless. If i < myArray.count, then [myArray objectAtIndex:i] cannot possibly be nil. [myArray objectAtIndex:i] will never, ever, ever return nil.

NSArray not deallocating in ARC Objective-C

I am trying to write a command line application in Objective-C for a university project. The project needs matrix manipulation so I have written a class to handle all the matrix methods (Addition and multiplication and such). My matrix methods look like this:
- (NSArray *)sumMatrices:(NSArray *)matrices
{
NSMutableArray *sum = [[NSMutableArray alloc] init];
NSInteger cols = [matrices[0][0] count];
NSInteger rows = [matrices[0] count];
for (int i = 0; i < rows; i++) {
NSMutableArray *row = [[NSMutableArray alloc] init];
for (int j = 0; j < cols; j++) {
CGFloat value = 0.0;
for (NSArray *array in matrices) {
value += [array[i][j] doubleValue];
}
[row addObject:[NSNumber numberWithDouble:value]];
}
[sum addObject:[row copy]];
row = nil;
}
return [sum copy];
}
However theres is a massive problem with this programme, I having used objective-c for iOS expect ARC to handle all my memory allocation and deallocation without a problem, however in this case the NSMutableArray 'sum' is never being deallocated, and because this method is being called in a loop which runs 10's of thousands of times (Modelling a double pendulum using RK4) the memory usage builds up and makes the program extremely slow.
Is there any reason this NSMutableArray isn't being deallocated once this method has returned?
Your problem is less about this code and more about the code surrounding it. Let's assume for a moment that your code around it looks like this:
NSArray *matricies; //Declared somewhere else;
NSMutableArray *results = [[NSMutableArray alloc] init];
for (int i=0; i < [matricies count] - 1; i++) {
for (int j=i+1; j < [matricies count]; i++) {
NSArray *sum = [self sumMatrices:#[matricies[i], matricies[j]]];
[results addObject:sum];
}
}
The actual operations that I'm performing are not particularly relevant to this example. The code pattern is. You'll notice I'm using a nested "tight" loop. Control never returns to the run loop until AFTER all calculations are complete. Without ARC, your memory would be freed as soon as the last release was performed, excluding autoreleased objects. With ARC, your memory is not freed until control is returned to the runloop, much the same way autoreleased objects used to. As a result, your code will appear to leak, until processing is complete and the system decides it should release your memory. If the CPU is perpetually under a heavy load, it may not clean up memory until it absolutely has to.
There are a few cleaver ways to use #autoreleasepool to help in this case, but that will make your code significantly slower. Additionally, Objective C is a fairly slow language for objects and method calls. If you are using this code heavily, you should convert it into C or C++ and manage the memory yourself.
without going into much detail you can try to use autoreleasepool
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/memorymgmt/articles/mmAutoreleasePools.html
i would use copy if i want to preserve an array which gets modified but in your case do you really need it ?

Problems sending messages to NSMutableArrays within C-Arrays

I'm currently trying to implement a pooling system, I have all the code, I just dont understand why a certain part of it doesn't work.
I have a c-array of NSMutable array made like this:
NSMutableArray *poolArray[xSize][ySize];
for (int n = 0; n < xSize; n++)
{
for (int m = 0; m < ySize; m++)
{
poolArray[n][m] = [[NSMutableArray alloc] init];
}
}
And whilst trying to access it I get the x and y coordinate of the pool and object is in and try to add it like this:
[poolArray[x][y] addObject:object]; //This raises a EXC_BAD_ACCESS error
I am totally open to editing how I write this - I am aware that I could declare a NSMutableArray and use indexes of ((y * width) + x) and I may have to rewite the code like that. But preferably I dont want to have to do that as I only want to actually create the arrays I'm using so something like this:
if (poolArray[x][y] == nil) poolArray[x][y] = [[NSMutableArray alloc] init];
[poolArray[x][y] addObject:object];
This is so that it can have 'holes' so I dont have to make anything at poolArray[2][3] for example if there is nothing there.
I don't know if there is anyway that I could rewrite that with objective-c types, but if I do I'm forced to keep creating a NSMutableArray at every space, the reason I dont want to do that is because I want to get every little bit of performance I can out of the system.
Thanks for taking the time to read this, and any response is appreciated :)
This works for me:
#import <Foundation/Foundation.h>
#define xSize 10
#define ySize 10
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSMutableArray *poolArray[xSize][ySize];
for (int n = 0; n < xSize; n++)
{
for (int m = 0; m < ySize; m++)
{
poolArray[n][m] = [[NSMutableArray alloc] init];
}
}
[poolArray[2][3] addObject: #"Hello"];
[poolArray[2][3] addObject: #"world!"];
NSLog(#"poolArray[2][3] objects: %# %#",
[poolArray[2][3] objectAtIndex: 0],
[poolArray[2][3] objectAtIndex: 1]);
[pool drain];
return 0;
}
(Yes, I know, I should release all NSMutableArray instances. Left out for brevity).
So there are a few things you should check:
Is object a valid object, i.e. was it initialized? The NSMutableArray will try to retain the object, and if it was never initialized, that will fail miserably, or if it was dealloc-ed already, it will fail too.
are x and y valid? You can easily go over the boundaries and not notice it.
Can't see anything wrong with the code you've provided, although a couple of ideas:
In the case where your checking poolArray[x][y] == nil have you actually reset all the values to nil when you initialize the array?
An alternative that should work, is to store the array on the heap. You could use calloc (which will initialize the memory to 0), or malloc and memset.
The following should work:
NSMutableArray ***poolArray = calloc(xSize * ySize, sizeof(NSMutableArray *));
if (poolArray[x][y] == nil) poolArray[x][y] = [[NSMutableArray alloc] init];
[poolArray[x][y] addObject:object];