| // Copyright 2019 The Marl Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // This is an example application that uses Marl to find and print all the prime |
| // numbers in the range 1 to 10000000. |
| |
| #include "marl/defer.h" |
| #include "marl/scheduler.h" |
| #include "marl/thread.h" |
| #include "marl/ticket.h" |
| |
| #include <math.h> |
| |
| // searchMax defines the upper limit on primes to find. |
| constexpr int searchMax = 10000000; |
| |
| // searchChunkSize is the number of numbers searched, per task, for primes. |
| constexpr int searchChunkSize = 10000; |
| |
| // isPrime returns true if i is prime. |
| bool isPrime(int i) { |
| auto c = static_cast<int>(sqrt(i)); |
| for (int j = 2; j <= c; j++) { |
| if (i % j == 0) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| int main(int argc, const char** argv) { |
| (void)argc; // unused parameter |
| (void)argv; // unused parameter |
| |
| // Create a marl scheduler using the full number of logical cpus. |
| // Bind this scheduler to the main thread so we can call marl::schedule() |
| marl::Scheduler scheduler; |
| scheduler.setWorkerThreadCount(marl::Thread::numLogicalCPUs()); |
| scheduler.bind(); |
| defer(scheduler.unbind()); // unbind before destructing the scheduler. |
| |
| // Create a ticket queue. This will be used to ensure that the primes are |
| // printed in ascending order. |
| marl::Ticket::Queue queue; |
| |
| // Iterate over the range [1, searchMax] in steps of searchChunkSize. |
| for (int searchBase = 1; searchBase <= searchMax; |
| searchBase += searchChunkSize) { |
| // Take a ticket from the ticket queue for this task. |
| auto ticket = queue.take(); |
| |
| // Schedule the task. |
| marl::schedule([=] { |
| // Find all the primes in [searchBase, searchBase+searchChunkSize-1]. |
| // Note this is run in parallel with the other scheduled tasks. |
| std::vector<int> primes; |
| for (int i = searchBase; i < searchBase + searchChunkSize; i++) { |
| if (isPrime(i)) { |
| primes.push_back(i); |
| } |
| } |
| |
| // Wait until the ticket is called. This ensures that the primes are |
| // printed in ascending order. This may cause this task to yield and allow |
| // other tasks to be executed while waiting for this ticket to be called. |
| ticket.wait(); |
| |
| // Print the primes. |
| for (auto prime : primes) { |
| printf("%d is prime\n", prime); |
| } |
| |
| // Call the next ticket so that those primes can be printed. |
| ticket.done(); |
| }); |
| } |
| |
| // take a ticket and wait on it to ensure that all the primes have been |
| // calculated and printed. |
| queue.take().wait(); |
| |
| return 0; |
| } |