Я пытаюсь использовать Alea для ускорения программы, над которой работаю, но мне нужна помощь.
Мне нужно сделать много побитовые и побитовые операции со значениями, хранящимися в двух массивах.
Для каждого элемента моего первого массива мне нужно выполнить побитовую операцию & с каждым элементом моего второго массива, затем подсчитайте биты, установленные в 1 результата &.
Если результат больше или равен определенному значению, мне нужно выйти из внутреннего for и перейти к следующему элементу моего первого массива.
Первый массив обычно большой, с миллионами элементов, второй обычно содержит менее 200 000 элементов.
Пытаемся выполнить все эти операции параллельно, вот мой код:
[GpuManaged]
private long[] Check(long[] arr1, long[] arr2, int limit)
{
Gpu.FreeAllImplicitMemory(true);
var gpu = Gpu.Default;
long[] result = new long[arr1.Length];
gpu.For(0, arr1.Length, i =>
{
bool found = false;
long b = arr1;
for (int i2 = 0; i2 < arr2.Length; i2++)
{
if (LibDevice.__nv_popcll(b & arr2[i2]) >= limit)
{
found = true;
break;
}
}
if (!found)
{
result = b;
}
});
return result;
}
Это работает, как и ожидалось, но немного быстрее, чем моя версия, работающая параллельно на четырехъядерном процессоре.
Я определенно что-то упускаю, это моя первая попытка написать код GPU.
Кстати, у меня NVIDIA — GeForce GT 740M. >
ИЗМЕНИТЬ
Следующий код в 2 раза быстрее предыдущего, по крайней мере, на моем ПК. Большое спасибо Майклу Рэндаллу за то, что он указал мне правильное направление.
private static int[] CheckWithKernel(Gpu gpu, int[] arr1, int[] arr2, int limit)
{
var lp = new LaunchParam(16, 256);
var result = new int[arr1.Length];
try
{
using (var dArr1 = gpu.AllocateDevice(arr1))
using (var dArr2 = gpu.AllocateDevice(arr2))
using (var dResult = gpu.AllocateDevice(arr1.Length))
{
gpu.Launch(Kernel, lp, arr1.Length, arr2.Length, dArr1.Ptr, dArr2.Ptr, dResult.Ptr, limit);
Gpu.Copy(dResult, result);
return result;
}
}
finally
{
Gpu.Free(arr1);
Gpu.Free(arr2);
Gpu.Free(result);
}
}
private static void Kernel(int a1, int a2, deviceptr arr1, deviceptr arr2, deviceptr arr3, int limit)
{
var iinit = blockIdx.x * blockDim.x + threadIdx.x;
var istep = gridDim.x * blockDim.x;
for (var i = iinit; i < a1; i += istep)
{
bool found = false;
int b = arr1;
for (var j = 0; j < a2; j++)
{
if (LibDevice.__nv_popcll(b & arr2[j]) >= limit)
{
found = true;
break;
}
}
if (!found)
{
arr3 = b;
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/490 ... h-alea-gpu
Ускорьте вложенные циклы и побитовые операции с помощью графического процессора Alea. ⇐ C#
Место общения программистов C#
1732662395
Anonymous
Я пытаюсь использовать Alea для ускорения программы, над которой работаю, но мне нужна помощь.
Мне нужно сделать много побитовые и побитовые операции со значениями, хранящимися в двух массивах.
Для каждого элемента моего первого массива мне нужно выполнить побитовую операцию & с каждым элементом моего второго массива, затем подсчитайте биты, установленные в 1 результата &.
Если результат больше или равен определенному значению, мне нужно выйти из внутреннего for и перейти к следующему элементу моего первого массива.
Первый массив обычно большой, с миллионами элементов, второй обычно содержит менее 200 000 элементов.
Пытаемся выполнить все эти операции параллельно, вот мой код:
[GpuManaged]
private long[] Check(long[] arr1, long[] arr2, int limit)
{
Gpu.FreeAllImplicitMemory(true);
var gpu = Gpu.Default;
long[] result = new long[arr1.Length];
gpu.For(0, arr1.Length, i =>
{
bool found = false;
long b = arr1[i];
for (int i2 = 0; i2 < arr2.Length; i2++)
{
if (LibDevice.__nv_popcll(b & arr2[i2]) >= limit)
{
found = true;
break;
}
}
if (!found)
{
result[i] = b;
}
});
return result;
}
Это работает, как и ожидалось, но немного быстрее, чем моя версия, работающая параллельно на четырехъядерном процессоре.
Я определенно что-то упускаю, это моя первая попытка написать код GPU.
Кстати, у меня NVIDIA — GeForce GT 740M. >
[b]ИЗМЕНИТЬ[/b]
Следующий код в 2 раза быстрее предыдущего, по крайней мере, на моем ПК. Большое спасибо Майклу Рэндаллу за то, что он указал мне правильное направление.
private static int[] CheckWithKernel(Gpu gpu, int[] arr1, int[] arr2, int limit)
{
var lp = new LaunchParam(16, 256);
var result = new int[arr1.Length];
try
{
using (var dArr1 = gpu.AllocateDevice(arr1))
using (var dArr2 = gpu.AllocateDevice(arr2))
using (var dResult = gpu.AllocateDevice(arr1.Length))
{
gpu.Launch(Kernel, lp, arr1.Length, arr2.Length, dArr1.Ptr, dArr2.Ptr, dResult.Ptr, limit);
Gpu.Copy(dResult, result);
return result;
}
}
finally
{
Gpu.Free(arr1);
Gpu.Free(arr2);
Gpu.Free(result);
}
}
private static void Kernel(int a1, int a2, deviceptr arr1, deviceptr arr2, deviceptr arr3, int limit)
{
var iinit = blockIdx.x * blockDim.x + threadIdx.x;
var istep = gridDim.x * blockDim.x;
for (var i = iinit; i < a1; i += istep)
{
bool found = false;
int b = arr1[i];
for (var j = 0; j < a2; j++)
{
if (LibDevice.__nv_popcll(b & arr2[j]) >= limit)
{
found = true;
break;
}
}
if (!found)
{
arr3[i] = b;
}
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/49027823/speed-up-nested-loops-and-bitwise-operations-with-alea-gpu[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия