28

My app uses an NSOperationQueue to cache thumbnail images in a background thread. On the iPad2 I can push the concurrent task count limit up to 5 or 6, but on single core devices like the iPad 1 this brings the UI to a grinding halt.

So, I'd like to detect a dual core device (currently only iPad 2) and adapt the concurrent limit appropriately. I know I'm not supposed to check model numbers, rather device features. So what device feature should I be looking for that would tell me whether the cpu is dual core?

damian
  • 3,604
  • 1
  • 27
  • 46
  • See this question: http://stackoverflow.com/questions/5337924/ipad-2-detection – Pontus Granström Aug 30 '11 at 10:44
  • 2
    Thanks, but I saw that one already. This might be being pedantic but I'd rather not detect a camera as I can't guarantee there won't be a dual core device *without* a camera in the future. – damian Aug 30 '11 at 11:00
  • 2
    Why do you feel the need to adjust the concurrent operation count manually? From the Concurrency Programming Guide: "Operation queues work with the system to restrict the number of concurrent operations to a value that is appropriate for the available cores and system load." GCD global concurrent queues should also be load balanced appropriately without any manual intervention. – Brad Larson Aug 30 '11 at 21:44
  • 2
    If I leave the concurrent task limit at its default, it makes scrolling the GUI (a UITableView with large thumbnail images) very jerky. Limiting the task limit to 1 reduces the jerkiness on single core devices, limiting it to 3 or 4 reduces the jerkiness on dual core devices. – damian Aug 31 '11 at 05:55
  • 4
    @damian, I've seen exactly the same thing. I find that letting NSOpQ handle the threads itself tends to over-commit the CPU and run much slower. I've spent hours trying to come up with ways to reliably get NSOpQ's defaults to work as quickly and easily as just setting maxConcurrentOperationsCount by hand when the operations are CPU bound and you have more than a handful of operations. – Rob Napier Aug 10 '12 at 01:37

7 Answers7

49

Method 1

[[NSProcessInfo processInfo] activeProcessorCount];

NSProcessInfo also has a processorCount property. Learn the difference here.

Method 2

#include <mach/mach_host.h>

unsigned int countCores()
{
  host_basic_info_data_t hostInfo;
  mach_msg_type_number_t infoCount;

  infoCount = HOST_BASIC_INFO_COUNT;
  host_info( mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount ) ;

  return (unsigned int)(hostInfo.max_cpus);
}

Method 3

#include <sys/sysctl.h>

unsigned int countCores()
{
  size_t len;
  unsigned int ncpu;

  len = sizeof(ncpu);
  sysctlbyname ("hw.ncpu",&ncpu,&len,NULL,0);

  return ncpu;
}
Community
  • 1
  • 1
albertamg
  • 28,492
  • 6
  • 64
  • 71
4

Just use:

[[NSProcessInfo processInfo] processorCount]

cprcrack
  • 17,118
  • 7
  • 88
  • 91
4

In Swift you can detect / print the number of active processors with the following code:

let processInfo = ProcessInfo()
print(processInfo.activeProcessorCount)

This code does not need any extra header files or frameworks and works completely natively.

Luke Pearce
  • 133
  • 1
  • 3
3

I guess this needs a separate answer rather than a comment:

I wonder what does the number of cores means now that apple brought more asymmetric processing with A10 fusion? Do we have 2.2 cores or 4 cores? apple neglected to make activeProcessorCount float to account for it's fractal nature. note it was like so even before fusion cause they likely had thermal throttling back then. They need either fix overcomittal of nsoperationqueue or come up with a float equivalent for activeProcessorCount and deprecate the activeProcessorCount in its current form that is losing its utility in the face of recent hw advancements

So the faster the Moore's law falls into oblivion or receives a shiny new constant the more meaningless core counting becomes. Unless you are writing some sort of a Geek Bench 42, multicore score edition.

Living in the late 2016, to address the underlying issue you are facing rather than hacking through with max concurrent operation prop I assume you have adjusted the QoS for the NSOperationQueue to .Background?

Me thinks this is a cleaner way to solve your problem with modern ios sdk then counting 'em cores using miles of rope courtesy of albertamg

Also please take a look at NSProcessInfoThermalStateDidChangeNotification (macos) and NSProcessInfo.lowPowerModeEnabled (ios) (I guess an alternative to observing NSProcessInfoThermalStateDidChangeNotification is to KVo on activeProcessorCount new value)

if you start to account for those new realities, the magic constants adjustments for multiplying core count would get interesting very fast... and rot as the new hardware rolls out of cupertino.

And it will be just about as easy to get it right on the current zoo of Apple hw as to get socket-level networking working correctly: doable, but by select few in Cupetino with iSteve shadow looming over the shoulder checking quality ;-)

Anton Tropashko
  • 5,486
  • 5
  • 41
  • 66
  • Positive vote for the suggestion: don't muck about with trying to effect queue prioritisation for yourself based on guessing from metrics; on iOS 8+ just set the queue priorities and let the OS deal with it. – Tommy Sep 30 '16 at 15:16
  • thanks, i've added more fodder for a usenet flame war into my answer – Anton Tropashko Sep 30 '16 at 15:28
2

Among other things, you can get that information through a system call...

NSDictionary dictionaryWithObjectsAndKeys:
    [self machineType],@"MachineType",
    [self humanMachineType],@"HumanMachineType",
    [self powerPCTypeString],@"ProcessorType",
    [NSNumber numberWithLong:
                     [self processorClockSpeed]],
                         @"ProcessorClockSpeed",
    [NSNumber numberWithLong:
                     [self processorClockSpeedInMHz]],
                         @"ProcessorClockSpeedInMHz",
    [NSNumber numberWithInt:[self countProcessors]],
                     @"CountProcessors",
    [self computerName],@"ComputerName",
    [self computerSerialNumber],@"ComputerSerialNumber",
    [self operatingSystemString],@"OperatingSystem",
    [self systemVersionString],@"SystemVersion",        
    nil];

Here's the reference... http://cocoadev.com/HowToGetHardwareAndNetworkInfo

jyliang
  • 198
  • 2
  • 7
paullj1
  • 127
  • 2
  • 12
  • This isn't really telling the OP anything useful; the link is helpful, but the only useful info in the link is the actual method implementations, not how to call them. – pasawaya Sep 13 '12 at 00:49
  • While this is useful, I dislike the error-prone nature of passing hard coded strings. Plus my inner miser notices that somewhere in there is going to be a `strcmp`, when a simple `==` on a primitive type would do.. :) – bobobobo Aug 14 '13 at 17:58
  • @paullj1 The link seems to be broken – Ayan Sengupta Nov 20 '13 at 19:45
1

Swift 5

To obtain logical cores count use this snippet:

let logicalCoresCount = ProcessInfo.processInfo.processorCount

To obtain physical cores count use below one:

func physicalCoresCount() -> UInt {

    var size: size_t = MemoryLayout<UInt>.size
    var coresCount: UInt = 0

    sysctlbyname("hw.physicalcpu", &coresCount, &size, nil, 0)

    return coresCount
}
Evgeny Karkan
  • 8,782
  • 2
  • 32
  • 38
1

I guess:

sysctl(HW_NCPU) 

or

sysctlbyname("hw.ncpu", NULL, &size, NULL, 0);

should work.

you can modify code from: Detect the specific iPhone/iPod touch model

Community
  • 1
  • 1
Deniz Mert Edincik
  • 4,336
  • 22
  • 24