You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
5.0 KiB
Python

import math
from time import time
import pycuda.autoinit
import pycuda.driver as drv
4 years ago
import numpy as np
from pycuda import gpuarray
from pycuda.compiler import SourceModule
4 years ago
from optparse import OptionParser
ker = SourceModule("""
__global__ void
check_prime(unsigned long long *input, bool *output)
{
int i = threadIdx.x + blockDim.x * blockIdx.x;
unsigned long long num = input[i];
if (num == 2) {
output[i] = true;
return;
} else if (num < 3 || num % 2 == 0) {
return;
}
unsigned long long limit = (long) sqrt((double) num) + 1;
for (unsigned long long i = 3; i <= limit; i += 2) {
if (num % i == 0) {
return;
}
}
output[i] = true;
}
""")
ker2 = SourceModule("""
__global__ void check_prime2(const unsigned long long *IN, bool *OUT) {
int id = threadIdx.x + blockDim.x * blockIdx.x;
unsigned long long num = IN[id];
unsigned long long limit = (unsigned long long) sqrt((double) num) + 1;
if (num == 2 || num == 3) {
OUT[id] = true;
return;
} else if (num == 1 || num % 2 == 0) {
return;
}
if (limit < 9) {
for (unsigned long long i = 3; i <= limit; i++) {
if (num % i == 0) {
return;
}
}
} else {
if (num > 3 && num % 3 == 0) {
return;
}
for (unsigned long long i = 9; i <= (limit + 6); i += 6) {
if (num % (i - 2) == 0 || num % (i - 4) == 0) {
return;
}
}
}
OUT[id] = true;
}
""")
def calc_primes(start: int = 1, grid_size: int = 1000, block_size: int = 1024):
check_prime = ker2.get_function("check_prime2")
primes = []
if start < 2:
primes = [2]
start = 3
if start % 2 == 0:
start = start + 1
startEvent = drv.Event()
endEvent = drv.Event()
testvec = np.arange(start, block_size * grid_size * 2 + start, step=2).astype(np.ulonglong)
testvec_gpu = gpuarray.to_gpu(testvec)
outvec_gpu = gpuarray.to_gpu(np.full(block_size * grid_size, False, dtype=bool))
startEvent.record()
check_prime(testvec_gpu, outvec_gpu, block=(block_size, 1, 1), grid=(grid_size, 1, 1))
endEvent.record()
endEvent.synchronize()
kernel_execution_time = startEvent.time_till(endEvent)
result = outvec_gpu.get()
for idx, val in enumerate(result):
if val:
primes.append(testvec[idx])
4 years ago
print('checked ' + str(block_size * grid_size) + ' numbers' + ' (' + str(start) + ' - ' + str(
start + block_size * grid_size) + ')')
print('last prime: ' + str(primes[-1]))
print('The GPU needed ' + str(kernel_execution_time) + ' milliseconds')
4 years ago
with open(options.timings_output, 'a') as file:
file.write(str(start) + "," + str(kernel_execution_time) + "," + str((block_size * grid_size)/(kernel_execution_time/1000)) + "\n")
4 years ago
return primes
4 years ago
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-e", "--end", dest="end",
help="numbers to check without even numbers", default="50000000", type="int")
parser.add_option("--numbers-per-step", dest="numbers_per_step",
help="amount of uneven numbers checked in each step (even number are skipped)", default="12288",
type="int")
parser.add_option("--block_size", dest="block_size",
help="number of threads per block, max = 1024", default="128",
type="int")
parser.add_option("--grid_size", dest="grid_size",
help="number of blocks in the grid",
type="int")
parser.add_option("--output", dest="output",
help="name of the file, where the primes should be stored", default="primes.txt", type="string")
parser.add_option("--timings-output", dest="timings_output",
help="name of the csv file, where the timing is logged as csv", default="timings.csv",
type="string")
parser.add_option("--save-primes", dest="save_primes",
help="whether the calculated primes should be saved in a txt file", default=False)
(options, args) = parser.parse_args()
4 years ago
block_size = options.block_size
start = 1
grid_size = int(math.ceil(options.numbers_per_step / block_size))
resulting_numbers_per_step = block_size * grid_size
last_number_checked = start - 1
4 years ago
with open(options.timings_output, 'w') as file:
file.write("offset,duration,numbers_per_second\n")
if options.save_primes:
with open(options.output, 'w') as file:
file.write("")
4 years ago
while last_number_checked < options.end:
calculated_primes = calc_primes(last_number_checked + 1, grid_size, block_size)
if options.save_primes:
with open(options.output, 'a') as file:
file.write("\n".join([str(p) for p in calculated_primes]))
last_number_checked = last_number_checked + resulting_numbers_per_step * 2