/* //@HEADER // ************************************************************************ // // Kokkos v. 2.0 // Copyright (2014) Sandia Corporation // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the name of the Corporation nor the names of the // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Questions? Contact Christian R. Trott (crtrott@sandia.gov) // // ************************************************************************ //@HEADER */ #include #include #include #include // Type of a one-dimensional length-N array of int. typedef Kokkos::View view_type; typedef view_type::HostMirror host_view_type; // This is a "zero-dimensional" View, that is, a View of a single // value (an int, in this case). Access the value using operator() // with no arguments: e.g., 'count()'. // // Zero-dimensional Views are useful for reduction results that stay // resident in device memory, as well as for irregularly updated // shared state. We use it for the latter in this example. typedef Kokkos::View count_type; typedef count_type::HostMirror host_count_type; // Functor for finding a list of primes in a given set of numbers. If // run in parallel, the order of results is nondeterministic, because // hardware atomic updates do not guarantee an order of execution. struct findprimes { view_type data; view_type result; count_type count; findprimes (view_type data_, view_type result_, count_type count_) : data (data_), result (result_), count (count_) {} // Test if data(i) is prime. If it is, increment the count of // primes (stored in the zero-dimensional View 'count') and add the // value to the current list of primes 'result'. KOKKOS_INLINE_FUNCTION void operator() (const int i) const { const int number = data(i); // the current number // Test all numbers from 3 to ceiling(sqrt(data(i))), to see if // they are factors of data(i). It's not the most efficient prime // test, but it works. const int upper_bound = std::sqrt(1.0*number)+1; bool is_prime = !(number%2 == 0); int k = 3; while (k < upper_bound && is_prime) { is_prime = !(number%k == 0); k += 2; // don't have to test even numbers } if (is_prime) { // Use an atomic update both to update the current count of // primes, and to find a place in the current list of primes for // the new result. // // atomic_fetch_add results the _current_ count, but increments // it (by 1 in this case). The current count of primes indexes // into the first unoccupied position of the 'result' array. const int idx = Kokkos::atomic_fetch_add (&count(), 1); result(idx) = number; } } }; int main () { Kokkos::initialize (); { srand (61391); // Set the random seed int nnumbers = 100000; view_type data ("RND", nnumbers); view_type result ("Prime", nnumbers); count_type count ("Count"); host_view_type h_data = Kokkos::create_mirror_view (data); host_view_type h_result = Kokkos::create_mirror_view (result); host_count_type h_count = Kokkos::create_mirror_view (count); typedef view_type::size_type size_type; // Fill the 'data' array on the host with random numbers. We assume // that they come from some process which is only implemented on the // host, via some library. (That's true in this case.) for (size_type i = 0; i < data.extent(0); ++i) { h_data(i) = rand () % nnumbers; } Kokkos::deep_copy (data, h_data); // copy from host to device Kokkos::parallel_for (data.extent(0), findprimes (data, result, count)); Kokkos::deep_copy (h_count, count); // copy from device to host printf ("Found %i prime numbers in %i random numbers\n", h_count(), nnumbers); } Kokkos::finalize (); }