c - 在 CUDA 上与 RSA 加密作斗争
问题描述
我正在尝试使用 CUDA 使用 RSA 算法来加速加密。我无法在内核函数中正确执行幂模运算。
我在 AWS 上使用 Cuda 编译工具,版本 9.0,V9.0.176 进行编译。
#include <cstdio>
#include <math.h>
#include "main.h"
// Kernel function to encrypt the message (m_in) elements into cipher (c_out)
__global__
void enc(int numElements, int e, int n, int *m_in, int *c_out)
{
int index = blockIdx.x * blockDim.x + threadIdx.x;
int stride = blockDim.x * gridDim.x;
printf("e = %d, n = %d, numElements = %d\n", e, n, numElements);
for (int i = index; i < numElements; i += stride)
{
// POINT OF ERROR //
// c_out[i] = (m_in[i]^e) % n; //**GIVES WRONG RESULTS**
c_out[i] = __pow(m_in[i], e) % n; //**GIVES, error: expression must have integral or enum type**
}
}
// This function is called from main() from other file.
int* cuda_rsa(int numElements, int* data, int public_key, int key_length)
{
int e = public_key;
int n = key_length;
// Allocate Unified Memory – accessible from CPU or GPU
int* message_array;
cudaMallocManaged(&message_array, numElements*sizeof(int));
int* cipher_shared_array; //Array shared by CPU and GPU
cudaMallocManaged(&cipher_shared_array, numElements*sizeof(int));
int* cipher_array = (int*)malloc(numElements * sizeof(int));
//Put message array to be encrypted in a managed array
for(int i=0; i<numElements; i++)
{
message_array[i] = data[i];
}
// Run kernel on 16M elements on the GPU
enc<<<1, 1>>>(numElements, e, n, message_array, cipher_shared_array);
// Wait for GPU to finish before accessing on host
cudaDeviceSynchronize();
//Copy into a host array and pass it to main() function for verification.
//Ignored memory leaks.
for(int i=0; i<numElements; i++)
{
cipher_array[i] = cipher_shared_array[i];
}
return (cipher_array);
}
请帮我解决这个错误。如何在 CUDA 内核上实现幂模(如下)?
(x ^ y) % n;
我真的很感激任何帮助。
解决方案
在 C 或 C++ 中,这是:
(x^y)
不会将 x 提高到 y 的幂。 它执行按位异或运算。这就是为什么您的第一个认识没有给出正确答案的原因。
在 C 或 C++ 中,模算术运算符:
%
只为整数参数定义。即使您将整数传递给__pow()
函数,该函数的返回结果也是 a double
(即浮点数,而不是整数)。
我不知道你需要执行的数学的细节,但是如果你将结果__pow
转换为int
(例如)这个编译错误将会消失。 对于您希望执行的任何算术,这可能有效也可能无效。(例如,您可能希望将其转换为“长”整数。)
这样做之后,您将遇到另一个编译错误。最简单的方法是使用pow()
而不是__pow()
:
c_out[i] = (int)pow(m_in[i], e) % n;
如果您实际上是在尝试使用CUDA 快速数学内在函数,则应该使用__powf
not __pow
:
c_out[i] = (int)__powf(m_in[i], e) % n;
请注意,快速数学内在函数通常会降低精度。
由于这些升幂函数正在执行浮点运算(即使您正在传递整数),所以可能会得到一些可能出乎意料的结果。例如,如果您将 5 提高到 2 的幂,则可能得到 24.9999999999 而不是 25。如果您只是将其转换为整数,您将截断为 24。因此您可能需要探索将结果四舍五入到最接近的整数,而不是强制转换。但同样,我还没有研究过你想要执行的数学。
推荐阅读
- reactjs - 正确更新 React 状态
- angular - 无法在角度材料数据表中显示 json
- python - OSError: [Errno 22] 打开文件时参数无效
- c - c语言中的低级访问是什么意思?
- version-control - 我应该如何/何时更新版本号?
- c++ - 如何进行 gtkmm 线程安全队列绘制?
- python - 使用 pandas 或 Numpy 根据列数据选择一系列行
- python - 在 hive 表中将 json 对象作为 blob/clob 插入(不想定义像 avro/parquet 这样的模式)
- angular - 子模块中的角度重复导入
- c# - .NET Web 服务 - 如何查看 WSDL 文件中的验证规则