| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- /*
- * cudadl version 0.9: Compute discrete logs in smooth group orders
- * using CUDA
- * Copyright (C) 2012 by Ryan Henry and Ian Goldberg
- * {rhenry,iang}@cs.uwaterloo.ca
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of version 3 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #ifndef __DPSTREAM_H__
- #define __DPSTREAM_H__
- #include <sm_20_atomic_functions.h>
- #include <unistd.h>
- /* Routines to allow CUDA threads to write distinguished points into
- a buffer that will be read by the host */
- __constant__ static unsigned int *DPbuffer = NULL;
- __constant__ static unsigned int DPbuffersize = 0; // in words
- static unsigned int *DPbuffer_device = NULL;
- __device__ volatile static unsigned int DPbuffertail = 0; // in words
- static const unsigned int DPrecordsize = (1+WORDS+6); // in words
- static unsigned int DPbufsize = 0;
- cudaError_t DPstreamInit(size_t numrecords)
- {
- // Allocate the buffer
- DPbufsize = DPrecordsize * numrecords;
- if (cudaMalloc((void **)&DPbuffer_device, DPbufsize * sizeof(unsigned int))
- != cudaSuccess) {
- return cudaErrorInitializationError;
- }
- // Zero it
- cudaMemset(DPbuffer_device, 0, DPbufsize * sizeof(unsigned int));
- // Initialize the device-visible pointers
- unsigned int zero = 0;
- cudaMemcpyToSymbol(DPbuffer, &DPbuffer_device, sizeof(unsigned int*));
- cudaMemcpyToSymbol(DPbuffersize, &DPbufsize, sizeof(unsigned int));
- cudaMemcpyToSymbol(DPbuffertail, &zero, sizeof(unsigned int));
- return cudaSuccess;
- }
- void DPstreamEnd(void)
- {
- if (DPbuffer_device) {
- cudaFree(DPbuffer_device);
- }
- DPbuffer_device = NULL;
- }
- // Call this from the device to write the following into the buffer:
- // block and thread indices (1 word total)
- // x (WORDS words)
- // a (2 words)
- // b (2 words)
- __device__ inline unsigned int *DPstreamAlloc()
- {
- if (!DPbuffer) return NULL;
- // Atomically increment the DPbuffertail
- if (DPbuffertail >= DPbuffersize) return NULL;
- unsigned int ouroffset = atomicAdd((unsigned int *)&DPbuffertail,
- (unsigned int) (DPrecordsize));
- if (ouroffset + DPrecordsize > DPbuffersize) {
- atomicSub((unsigned int *)&DPbuffertail, (unsigned int)DPrecordsize);
- return NULL;
- }
- unsigned int *ourbuffer = DPbuffer + ouroffset;
- return ourbuffer;
- }
- // dp points to an array of WORDS+7 unsigned ints:
- // - 1 word of threadID/blockID
- // - WORDS words of the dp value
- // - 3 words of a
- // - 3 words of b
- extern bool dpcallback(void *data, unsigned int *dpwords);
- // Return true if we should stop computing
- bool DPstreamParse(void *data)
- {
- // Get the number of words in the buffer
- unsigned int bufsize;
- cudaMemcpyFromSymbol(&bufsize, DPbuffertail, sizeof(unsigned int));
- #ifdef VERBOSE
- cerr << getpid() << " " << bufsize / DPrecordsize << " DPs\n";
- #endif
- unsigned int *dpbuf = (unsigned int*)calloc(bufsize, sizeof(unsigned int));
- bool stop_computing = false;
- if (dpbuf) {
- cudaMemcpy(dpbuf, DPbuffer_device, bufsize * sizeof(unsigned int),
- cudaMemcpyDeviceToHost);
- for (unsigned int *dp=dpbuf; dp < dpbuf+bufsize; dp += DPrecordsize) {
- if (dpcallback(data, dp)) {
- stop_computing = true;
- }
- }
- }
- free(dpbuf);
- // Reset the buffer
- unsigned int zero = 0;
- cudaMemcpyToSymbol(DPbuffertail, &zero, sizeof(unsigned int));
- return stop_computing;
- }
- #endif
|