import pycuda.autoinit
# from pycuda import curandom
from pycuda import gpuarray
from pycuda.compiler import SourceModule
# from pycuda.tools import DeviceData
import numpy as np
from pythonGMMLL import pythonLL

#prepare for global usage


def largertest(numRuns = 1000, numPoints = 512, dim = 13, numMixtures = 8):



	with open("../Cuda/KernelV2.cu") as f:
		if numPoints>=1024:
			mod = SourceModule(f.read().replace('512', '1024'))
			numThreads = 1024
		else:
			mod = SourceModule(f.read())
			numThreads = 512

	if numPoints>numThreads:
		numBlocks = numPoints/numThreads
		if numPoints%numThreads != 0: numBlocks+=1
	else:
		numBlocks=1

	print "numBlocks: {}, numPoints: {}".format(numBlocks, numPoints)

	likelihoodKernel = mod.get_function("likelihoodKernel")
	likelihoodKernel.prepare('PPPPiiiP')

	Xpoints = np.random.normal(size=(numPoints,dim)).astype(np.float32)
	means = np.random.normal(size=(numMixtures,dim)).astype(np.float32)
	diagCovs = np.random.uniform(size=(numMixtures,dim)).astype(np.float32)
	weights = np.random.uniform(size=numMixtures).astype(np.float32)
	weights/=np.sum(weights)



	Xpoints_gpu = gpuarray.to_gpu_async(Xpoints)
	diagCovs_gpu = gpuarray.to_gpu_async(diagCovs)
	means_gpu = gpuarray.to_gpu_async(means)
	weights_gpu = gpuarray.to_gpu_async(weights)
	emptyLikelihood_gpu = gpuarray.zeros(shape = int(numBlocks), dtype = np.float32)



	for i in xrange(numRuns):
		if i%100==0: 
			print "At {} iterations".format(i)
			
		likelihoodKernel.prepared_call((numBlocks,1), (numThreads, 1,1),  
		Xpoints_gpu.gpudata, means_gpu.gpudata, diagCovs_gpu.gpudata, weights_gpu.gpudata, 
		dim, numPoints, numMixtures,	
		emptyLikelihood_gpu.gpudata)
		ll = np.sum(emptyLikelihood_gpu.get())

	print ll

	# tp =  pythonLL(Xpoints, means, diagCovs, weights)
	# print "Correct value: ", tp


if __name__ == '__main__':
	import sys
	if len(sys.argv) == 3:
		largertest(numRuns = int(sys.argv[1]), numPoints = int(sys.argv[2]), dim = 13, numMixtures = 8)
		# main(, )
		#We have a input length and numRuns length
	elif len(sys.argv)==2:
		largertest(numRuns = 1000, numPoints = int(sys.argv[1]), dim = 13, numMixtures = 8)
	elif len(sys.argv)==1:
		#run with default
		largertest(numRuns = 1000, numPoints = 64, dim = 13, numMixtures = 8)
	else:
		print "Failure"


import pycuda.autoinit
# from pycuda import curandom
from pycuda import gpuarray
from pycuda.compiler import SourceModule
# from pycuda.tools import DeviceData
import numpy as np
from pythonGMMLL import pythonLL

#prepare for global usage


def largertest(numRuns = 1000, numPoints = 512, dim = 13, numMixtures = 8):



	with open("../Cuda/KernelV2.cu") as f:
		if numPoints>=1024:
			mod = SourceModule(f.read().replace('512', '1024'))
			numThreads = 1024
		else:
			mod = SourceModule(f.read())
			numThreads = 512

	if numPoints>numThreads:
		numBlocks = numPoints/numThreads
		if numPoints%numThreads != 0: numBlocks+=1
	else:
		numBlocks=1

	print "numBlocks: {}, numPoints: {}".format(numBlocks, numPoints)

	likelihoodKernel = mod.get_function("likelihoodKernel")
	likelihoodKernel.prepare('PPPPiiiP')

	Xpoints = np.random.normal(size=(numPoints,dim)).astype(np.float32)
	means = np.random.normal(size=(numMixtures,dim)).astype(np.float32)
	diagCovs = np.random.uniform(size=(numMixtures,dim)).astype(np.float32)
	weights = np.random.uniform(size=numMixtures).astype(np.float32)
	weights/=np.sum(weights)



	Xpoints_gpu = gpuarray.to_gpu_async(Xpoints)
	diagCovs_gpu = gpuarray.to_gpu_async(diagCovs)
	means_gpu = gpuarray.to_gpu_async(means)
	weights_gpu = gpuarray.to_gpu_async(weights)
	emptyLikelihood_gpu = gpuarray.zeros(shape = int(numBlocks), dtype = np.float32)



	for i in xrange(numRuns):
		if i%100==0: 
			print "At {} iterations".format(i)
			
		likelihoodKernel.prepared_call((numBlocks,1), (numThreads, 1,1),  
		Xpoints_gpu.gpudata, means_gpu.gpudata, diagCovs_gpu.gpudata, weights_gpu.gpudata, 
		dim, numPoints, numMixtures,	
		emptyLikelihood_gpu.gpudata)
		ll = np.sum(emptyLikelihood_gpu.get())

	print ll

	tp =  pythonLL(Xpoints, means, diagCovs, weights)
	print "Correct value: ", tp


if __name__ == '__main__':
	import sys
	if len(sys.argv) == 3:
		largertest(numRuns = int(sys.argv[1]), numPoints = int(sys.argv[2]), dim = 13, numMixtures = 8)
		# main(, )
		#We have a input length and numRuns length
	elif len(sys.argv)==2:
		largertest(numRuns = 1000, numPoints = int(sys.argv[1]), dim = 13, numMixtures = 8)
	elif len(sys.argv)==1:
		#run with default
		largertest(numRuns = 1000, numPoints = 64, dim = 13, numMixtures = 8)
	else:
		print "Failure"


Check high block vals