ich ein pycuda Programm hier haben, die von der Kommandozeile in einem Bild liest und speichert eine Version zurück mit den invertierten Farben:pyCuda, Fragen mehrere einzelne Variable Argumente Senden
import pycuda.autoinit
import pycuda.driver as device
from pycuda.compiler import SourceModule as cpp
import numpy as np
import sys
import cv2
modify_image = cpp("""
__global__ void modify_image(int pixelcount, unsigned char* inputimage, unsigned char* outputimage)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
if (id >= pixelcount)
return;
outputimage[id] = 255 - inputimage[id];
}
""").get_function("modify_image")
print("Loading image")
image = cv2.imread(sys.argv[1], cv2.IMREAD_UNCHANGED).astype(np.uint8)
print("Processing image")
pixels = image.shape[0] * image.shape[1]
newchannels = []
for channel in cv2.split(image):
output = np.zeros_like(channel)
modify_image(
device.In(np.int32(pixels)),
device.In(channel),
device.Out(output),
block=(1024,1,1), grid=(pixels // 1024 + 1, 1))
newchannels.append(output)
finalimage = cv2.merge(newchannels)
print("Saving image")
cv2.imwrite("processed.png", finalimage)
print("Done")
Es funktioniert völlig in Ordnung, auch auf größere Bilder. Beim Versuch, die Funktionalität des Programms zu erweitern, stieß ich jedoch auf ein wirklich seltsames Problem, bei dem das Hinzufügen eines zweiten Variablenarguments zum Kernel dazu führt, dass das Programm vollständig fehlschlägt und einfach ein vollständig schwarzes Bild gespeichert wird. Der folgende Code funktioniert nicht.
import pycuda.autoinit
import pycuda.driver as device
from pycuda.compiler import SourceModule as cpp
import numpy as np
import sys
import cv2
modify_image = cpp("""
__global__ void modify_image(int pixelcount, int width, unsigned char* inputimage, unsigned char* outputimage)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
if (id >= pixelcount)
return;
outputimage[id] = 255 - inputimage[id];
}
""").get_function("modify_image")
print("Loading image")
image = cv2.imread(sys.argv[1], cv2.IMREAD_UNCHANGED).astype(np.uint8)
print("Processing image")
pixels = image.shape[0] * image.shape[1]
newchannels = []
for channel in cv2.split(image):
output = np.zeros_like(channel)
modify_image(
device.In(np.int32(pixels)),
device.In(np.int32(image.shape[0])),
device.In(channel),
device.Out(output),
block=(1024,1,1), grid=(pixels // 1024 + 1, 1))
newchannels.append(output)
finalimage = cv2.merge(newchannels)
print("Saving image")
cv2.imwrite("processed.png", finalimage)
print("Done")
wo der einzige Unterschied auf zwei Zeilen ist, der Kernel-Header und es ist Aufruf. Der eigentliche Code des Kerns selbst ist unverändert, und dennoch bricht diese kleine Addition das Programm vollständig durch. Weder der Compiler noch der Interpreter werfen Fehler. Ich habe keine Ahnung, wie ich anfangen kann, es zu debuggen, und bin völlig verwirrt.
Ah, okay danke. Das macht sehr viel Sinn. Ich dachte, die In-und Out-Anrufe waren in allen Fällen notwendig, aber ich denke nicht – Maurdekye