Asenkronize CUDA/C++ örneklerinden birini kopyaladım ve ilkelliği değerlendirmek için değiştirdim. Benim sorunum, her basılı asal için, dizideki bir sonraki değerin bu değerin bir kopyası olmasıdır. Bu amaçlanan davranış mı yoksa örneği programladığım bir problem mi?CUDA hesaplamaları sonrasında dizideki yinelenen değerler
Kodu:
////////////////////////////////////////////////////////////////////////////
//
// Copyright 1993-2015 NVIDIA Corporation. All rights reserved.
//
// Please refer to the NVIDIA end user license agreement (EULA) associated
// with this source code for terms and conditions that govern your use of
// this software. Any use, reproduction, disclosure, or distribution of
// this software and related documentation outside the terms of the EULA
// is strictly prohibited.
//
////////////////////////////////////////////////////////////////////////////
//
// This sample illustrates the usage of CUDA events for both GPU timing and
// overlapping CPU and GPU execution. Events are inserted into a stream
// of CUDA calls. Since CUDA stream calls are asynchronous, the CPU can
// perform computations while GPU is executing (including DMA memcopies
// between the host and device). CPU can query CUDA events to determine
// whether GPU has completed tasks.
//
// includes, system
#include <stdio.h>
// includes CUDA Runtime
#include <cuda_runtime.h>
// includes, project
#include <helper_cuda.h>
#include <helper_functions.h> // helper utility functions
//set matrix to possible prime values
//evaluate if input is prime, sets variable to 0 if not prime
__global__ void testPrimality(int * g_data) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
g_data[idx] = 3 + idx/2;
if (g_data[idx] <= 3) {
if (g_data[idx] <= 1) {
g_data[idx] = 0;
}
}
else if (g_data[idx] % 2 == 0 || g_data[idx] % 3 == 0) {
g_data[idx] = 0;
}
else {
for (unsigned short i = 5; i * i <= g_data[idx]; i += 6) {
if (g_data[idx] % i == 0 || g_data[idx] % (i + 2) == 0) {
g_data[idx] = 0;
}
}
}
}
bool correct_output(int *data, const int n, const int x)
{
for (int i = 0; i < n; i++)
if (data[i] != x)
{
printf("Error! data[%d] = %d, ref = %d\n", i, data[i], x);
return false;
}
return true;
}
int main(int argc, char *argv[])
{
int devID;
cudaDeviceProp deviceProps;
printf("[%s] - Starting...\n", argv[0]);
// This will pick the best possible CUDA capable device
devID = findCudaDevice(argc, (const char **)argv);
// get device name
checkCudaErrors(cudaGetDeviceProperties(&deviceProps, devID));
printf("CUDA device [%s]\n", deviceProps.name);
const int n = 16 * 1024 * 1024;
int nbytes = n * sizeof(int);
int value = 1;
// allocate host memory
int *a = 0;
checkCudaErrors(cudaMallocHost((void **)&a, nbytes));
memset(a, 0, nbytes);
// allocate device memory
int *d_a=0;
checkCudaErrors(cudaMalloc((void **)&d_a, nbytes));
checkCudaErrors(cudaMemset(d_a, 255, nbytes));
// set kernel launch configuration
dim3 threads = dim3(512, 1);
dim3 blocks = dim3(n/threads.x, 1);
// create cuda event handles
cudaEvent_t start, stop;
checkCudaErrors(cudaEventCreate(&start));
checkCudaErrors(cudaEventCreate(&stop));
StopWatchInterface *timer = NULL;
sdkCreateTimer(&timer);
sdkResetTimer(&timer);
checkCudaErrors(cudaDeviceSynchronize());
float gpu_time = 0.0f;
// asynchronously issue work to the GPU (all to stream 0)
sdkStartTimer(&timer);
cudaEventRecord(start, 0);
cudaMemcpyAsync(d_a, a, nbytes, cudaMemcpyHostToDevice, 0);
//increment_kernel<<<blocks, threads, 0, 0>>>(d_a);
testPrimality<<<blocks, threads, 0, 0 >>>(d_a);
cudaMemcpyAsync(a, d_a, nbytes, cudaMemcpyDeviceToHost, 0);
cudaEventRecord(stop, 0);
sdkStopTimer(&timer);
// have CPU do some work while waiting for stage 1 to finish
unsigned long int counter=0;
while (cudaEventQuery(stop) == cudaErrorNotReady)
{
counter++;
}
checkCudaErrors(cudaEventElapsedTime(&gpu_time, start, stop));
// print the cpu and gpu times
printf("time spent executing by the GPU: %.2f\n", gpu_time);
printf("time spent by CPU in CUDA calls: %.2f\n", sdkGetTimerValue(&timer));
printf("CPU executed %lu iterations while waiting for GPU to finish\n", counter);
//print values for all allocated memory space
for (int i = 0; i < n; i++) {
if (a[i] != 0) {
std::cout << a[i]<< " : " << i << std::endl;
}
}
// check the output for correctness
//bool bFinalResults = correct_output(a, n, value);
bool bFinalResults = true;
// release resources
checkCudaErrors(cudaEventDestroy(start));
checkCudaErrors(cudaEventDestroy(stop));
checkCudaErrors(cudaFreeHost(a));
checkCudaErrors(cudaFree(d_a));
// cudaDeviceReset causes the driver to clean up all state. While
// not mandatory in normal operation, it is good practice. It is also
// needed to ensure correct operation when the application is being
// profiled. Calling cudaDeviceReset causes all profile data to be
// flushed before the application exits
cudaDeviceReset();
exit(bFinalResults ? EXIT_SUCCESS : EXIT_FAILURE);
}
Tamsayı 3'ten başlamayı deniyordum ve her bir ayrı hesaplama için 2'ye kadar artması gerekiyordu (çünkü asal sayılar hiçbir zaman eşit değildir). Bunu başarabileceğimi düşündüm çünkü idx her zaman 4'ün katları gibi görünüyordu. 2'lik bir artışla idx'i 2'ye bölebilirim diye düşündüm. – Stephen
O zaman belki 3+ 'idx' * 2. 'idx' sizin global olarak benzersiz iplik indeksinizdir ve sıfırdan başlar ve 0,1,2,3 vida dişi başına 1 artar. Yani, eğer 3.5,7,9 rakamsal bir giriş dizisi istiyorsanız ... doğru aritmetik 3 + 'idx' * 2 olacaktır. 'idx' size sahip olduğunuzdan, her zaman 4’ten fazla değil. –
Önerdiğiniz gibi yaptım, ancak yine de yinelenen değerler gibi görünüyor. – Stephen