Как сделать функцию ядра на массиве строк в Numba Cuda? - PullRequest
1 голос
/ 29 апреля 2019

У меня есть массив строк, которые я читаю из файла, я хочу сравнить каждую строку моего файла с определенной строкой .. файл слишком большой (около 200 МБ строк)

Я следовал этому уроку https://nyu -cds.github.io / python-numba / 05-cuda / , но он не показывает точно, как обращаться с массивом строк / символов.

import numpy as np
from numba import cuda



@cuda.jit
def my_kernel(io_array):

    tx = cuda.threadIdx.x

    ty = cuda.blockIdx.x

    bw = cuda.blockDim.x

    pos = tx + ty * bw
    if pos < io_array.size:  # Check array boundaries
        io_array[pos]   # i want here to compare each line of the string array to a specific line

def main():
    a = open("test.txt", 'r')  # open file in read mode

    print("the file contains:")
    data = country = np.array(a.read())


    # Set the number of threads in a block
    threadsperblock = 32

    # Calculate the number of thread blocks in the grid
    blockspergrid = (data.size + (threadsperblock - 1)) // threadsperblock

    # Now start the kernel
    my_kernel[blockspergrid, threadsperblock](data)


    # Print the result
    print(data)

if __name__ == '__main__':
        main()

У меня две проблемы.

Во-первых: как отправить мое предложение (строку), в котором я хочу сравнить каждую строку моего файла, с функцией kernal. (в массиве io_array без влияния на вычисление потоков)

Второе: это как бороться со строковым массивом? я получаю эту ошибку при запуске приведенного выше кода

this error is usually caused by passing an argument of a type that is unsupported by the named function.
[1] During: typing of intrinsic-call at test2.py (18)

File "test2.py", line 18:
def my_kernel(io_array):
    <source elided>
    if pos < io_array.size:  # Check array boundaries
        io_array[pos]   # do the computation

P.S. Я новичок в Cuda и только начал изучать его.

1 Ответ

2 голосов
/ 02 мая 2019

Прежде всего это:

data = country = np.array(a.read())

не делает то, что вы думаете, что делает. Это не приводит к массиву, который вы можете индексировать следующим образом:

io_array[pos]

Если вы мне не верите, просто попробуйте это в обычном коде Python с чем-то вроде:

print(data[0]) 

и вы получите ошибку. Если вам нужна помощь в этом, просто задайте свой вопрос по тегу python или numpy.

Итак, нам нужен другой метод для загрузки строковых данных с диска. Для простоты я выбрал numpy.fromfile(). Этот метод потребует, чтобы все строки в вашем файле были одинаковой ширины. Мне нравится эта концепция. Есть еще информация, которую вы должны будете описать, если хотите обрабатывать линии различной длины.

Если мы начнем таким образом, мы можем загрузить данные в виде массива байтов и использовать это:

$ cat test.txt
the quick brown fox.............
jumped over the lazy dog........
repeatedly......................
$ cat t43.py
import numpy as np
from numba import cuda

@cuda.jit
def my_kernel(str_array, check_str, length, lines, result):

    col,line = cuda.grid(2)
    pos = (line*(length+1))+col
    if col < length and line < lines:  # Check array boundaries
        if str_array[pos] != check_str[col]:
            result[line] = 0

def main():
    a = np.fromfile("test.txt", dtype=np.byte)
    print("the file contains:")
    print(a)
    print("array length is:")
    print(a.shape[0])
    print("the check string is:")
    b = a[33:65]
    print(b)
    i = 0
    while a[i] != 10:
        i=i+1
    line_length = i
    print("line length is:")
    print(line_length)
    print("number of lines is:")
    line_count = a.shape[0]/(line_length+1)
    print(line_count)
    res = np.ones(line_count)
    # Set the number of threads in a block
    threadsperblock = (32,32)

    # Calculate the number of thread blocks in the grid
    blocks_x = (line_length/32)+1
    blocks_y = (line_count/32)+1
    blockspergrid = (blocks_x,blocks_y)
    # Now start the kernel
    my_kernel[blockspergrid, threadsperblock](a, b, line_length, line_count, res)


    # Print the result
    print("matching lines (match = 1):")
    print(res)

if __name__ == '__main__':
        main()
$ python t43.py
the file contains:
[116 104 101  32 113 117 105  99 107  32  98 114 111 119 110  32 102 111
 120  46  46  46  46  46  46  46  46  46  46  46  46  46  10 106 117 109
 112 101 100  32 111 118 101 114  32 116 104 101  32 108  97 122 121  32
 100 111 103  46  46  46  46  46  46  46  46  10 114 101 112 101  97 116
 101 100 108 121  46  46  46  46  46  46  46  46  46  46  46  46  46  46
  46  46  46  46  46  46  46  46  10]
array length is:
99
the check string is:
[106 117 109 112 101 100  32 111 118 101 114  32 116 104 101  32 108  97
 122 121  32 100 111 103  46  46  46  46  46  46  46  46]
line length is:
32
number of lines is:
3
matching lines (match = 1):
[ 0.  1.  0.]
$
...