添加gf256的m4rie接口
This commit is contained in:
parent
011176d64c
commit
4d9f460888
45
README.md
Normal file
45
README.md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# cuElim
|
||||||
|
|
||||||
|
使用统一内存实现gf2^8域和素域上的矩阵乘法和高斯消元,无需考虑显存大小.
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
### 在现有项目中使用
|
||||||
|
|
||||||
|
1. 将`include`文件夹中的所有头文件添加到现有项目中.
|
||||||
|
|
||||||
|
2. 在需要使用gpu函数的地方引用`cuelim.cuh`
|
||||||
|
|
||||||
|
### 使用当前项目
|
||||||
|
|
||||||
|
1. 安装依赖
|
||||||
|
|
||||||
|
1. `C++ CUDA CMake ...`
|
||||||
|
2. [`GoogleTest`](https://github.com/google/googletest)
|
||||||
|
3. [`GoogleBenchmark`](https://github.com/google/benchmark)
|
||||||
|
|
||||||
|
2. 构建项目
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
make -j # 同时编译多个目标
|
||||||
|
ctest # 或make test 执行所有测试
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 运行可执行文件
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./cuelim # 执行主程序
|
||||||
|
./test/target # 执行特定测试
|
||||||
|
./benchmark/target # 执行特定性能测试
|
||||||
|
```
|
||||||
|
|
||||||
|
## 功能简介
|
||||||
|
|
||||||
|
- `gf256::MatGF256`:存储GF2^8矩阵,数据结构已经改为与m4rie一致,从低位到高位排列
|
||||||
|
- `gf256::ElimResult`:存储高斯消元的结果,包含秩、主元行(进行行交换前的位置)、主元列
|
||||||
|
- `gf256::ElimResult gf256::MatGF256::gpu_elim(const gf256::GF256 &gf)`:进行高斯消元
|
||||||
|
|
||||||
|
- `gfp::MatGFP`:储存GF65521矩阵,使用32位存储一个元素
|
||||||
|
- `gfp::ElimResult gfp::MatGFP::gpu_elim()`:进行高斯消元
|
@ -16,5 +16,4 @@ static void bench_gfp(benchmark::State &state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK(bench_gfp)->Args({10000, 10000, 10000});
|
BENCHMARK(bench_gfp)->Args({10000, 10000, 10000});
|
||||||
;
|
|
@ -106,7 +106,7 @@ namespace gf256
|
|||||||
GF256(base_t poly)
|
GF256(base_t poly)
|
||||||
{
|
{
|
||||||
assert(irreducible_polynomials_degree_08.count(poly) == 1);
|
assert(irreducible_polynomials_degree_08.count(poly) == 1);
|
||||||
this->poly = poly;
|
this->polynomial = poly;
|
||||||
for (size_t x = 0; x < (1 << gf256_len); x++)
|
for (size_t x = 0; x < (1 << gf256_len); x++)
|
||||||
{
|
{
|
||||||
mul_table[x][gf256_zero] = gf256_zero;
|
mul_table[x][gf256_zero] = gf256_zero;
|
||||||
@ -146,6 +146,11 @@ namespace gf256
|
|||||||
return inv_table[x];
|
return inv_table[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base_t poly(void) const
|
||||||
|
{
|
||||||
|
return polynomial;
|
||||||
|
}
|
||||||
|
|
||||||
inline cudaError_t cpy_to_constant() const
|
inline cudaError_t cpy_to_constant() const
|
||||||
{
|
{
|
||||||
return cudaMemcpyToSymbol(d_mul_table, mul_table, (1 << gf256_len) * (1 << gf256_len) * sizeof(gf256_t));
|
return cudaMemcpyToSymbol(d_mul_table, mul_table, (1 << gf256_len) * (1 << gf256_len) * sizeof(gf256_t));
|
||||||
@ -167,13 +172,13 @@ namespace gf256
|
|||||||
{
|
{
|
||||||
if (temp & (1 << i))
|
if (temp & (1 << i))
|
||||||
{
|
{
|
||||||
temp ^= poly << (i - gf256_len);
|
temp ^= polynomial << (i - gf256_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
base_t poly;
|
base_t polynomial;
|
||||||
gf256_t inv_table[1 << gf256_num];
|
gf256_t inv_table[1 << gf256_num];
|
||||||
gf256_t mul_table[1 << gf256_num][1 << gf256_num];
|
gf256_t mul_table[1 << gf256_num][1 << gf256_num];
|
||||||
};
|
};
|
||||||
|
@ -134,25 +134,6 @@ namespace gfp
|
|||||||
s_src[b_r][b_c] = s_src[b_r][b_c] ? gfprime - s_src[b_r][b_c] : 0;
|
s_src[b_r][b_c] = s_src[b_r][b_c] ? gfprime - s_src[b_r][b_c] : 0;
|
||||||
}
|
}
|
||||||
__syncthreads();
|
__syncthreads();
|
||||||
// if (bx == 0 && by == 0 && tid == 0)
|
|
||||||
// {
|
|
||||||
// for (int i = 0; i < StepSize; i++)
|
|
||||||
// {
|
|
||||||
// for (int j = 0; j < BlockRow; j++)
|
|
||||||
// {
|
|
||||||
// printf("%05d ", s_idx[i][j]);
|
|
||||||
// }
|
|
||||||
// printf("\n");
|
|
||||||
// }
|
|
||||||
// for (int i = 0; i < StepSize; i++)
|
|
||||||
// {
|
|
||||||
// for (int j = 0; j < BlockCol; j++)
|
|
||||||
// {
|
|
||||||
// printf("%05d ", s_src[i][j]);
|
|
||||||
// }
|
|
||||||
// printf("\n");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
for (int k = 0; k < rank; k++)
|
for (int k = 0; k < rank; k++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < BlockRow / THREAD_Y; j++)
|
for (int j = 0; j < BlockRow / THREAD_Y; j++)
|
||||||
|
41
include/interface.cuh
Normal file
41
include/interface.cuh
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef INTERFACE_CUH
|
||||||
|
#define INTERFACE_CUH
|
||||||
|
|
||||||
|
#include "cuelim.cuh"
|
||||||
|
#include <m4rie/m4rie.h>
|
||||||
|
|
||||||
|
void mzedread(mzed_t *A, gf256::MatGF256 &mat)
|
||||||
|
{
|
||||||
|
assert(A->nrows == mat.nrows && A->ncols == mat.ncols);
|
||||||
|
for (size_t r = 0; r < A->nrows; r++)
|
||||||
|
{
|
||||||
|
for (size_t cn = 0; cn < A->x->width; cn++)
|
||||||
|
{
|
||||||
|
*mat.at_base(r, cn) = A->x->rows[r][cn];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mzedwrite(gf256::MatGF256 &mat, mzed_t *A)
|
||||||
|
{
|
||||||
|
assert(A->nrows == mat.nrows && A->ncols == mat.ncols);
|
||||||
|
for (size_t r = 0; r < mat.nrows; r++)
|
||||||
|
{
|
||||||
|
for (size_t cn = 0; cn < mat.width; cn++)
|
||||||
|
{
|
||||||
|
A->x->rows[r][cn] = *mat.at_base(r, cn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t gpu_mzed_elim(mzed_t *A)
|
||||||
|
{
|
||||||
|
gf256::MatGF256 mat(A->nrows, A->ncols);
|
||||||
|
mzedread(A, mat);
|
||||||
|
gf256::GF256 gf256(A->finite_field->minpoly);
|
||||||
|
gf256::ElimResult res = mat.gpu_elim(gf256);
|
||||||
|
mzedwrite(mat, A);
|
||||||
|
return res.rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -20,5 +20,5 @@ bool test_gfp_elim(size_t rank, size_t rank_col, size_t nrows, size_t ncols, uin
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
cout << test_gfp_elim(1234, 2345, 3456, 4567, 41921095) << endl;
|
cout << test_gfp_elim(2000, 20000, 2500, 25000, 41921095) << endl;
|
||||||
}
|
}
|
@ -7,6 +7,7 @@ set(TEST_SRC_FILES
|
|||||||
"test_gf256_matrix.cu"
|
"test_gf256_matrix.cu"
|
||||||
"test_gf256_elim.cu"
|
"test_gf256_elim.cu"
|
||||||
"test_gfp_mul.cu"
|
"test_gfp_mul.cu"
|
||||||
|
"test_gfp_elim.cu"
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach(SRC ${TEST_SRC_FILES})
|
foreach(SRC ${TEST_SRC_FILES})
|
||||||
@ -16,13 +17,13 @@ foreach(SRC ${TEST_SRC_FILES})
|
|||||||
gtest_discover_tests(${SRC_NAME})
|
gtest_discover_tests(${SRC_NAME})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# set(TEST_M4RIE_SRC_FILES
|
set(TEST_M4RIE_SRC_FILES
|
||||||
# "test_m4rie_interface.cu"
|
"test_interface.cu"
|
||||||
# )
|
)
|
||||||
|
|
||||||
# foreach(SRC ${TEST_M4RIE_SRC_FILES})
|
foreach(SRC ${TEST_M4RIE_SRC_FILES})
|
||||||
# get_filename_component(SRC_NAME ${SRC} NAME_WE)
|
get_filename_component(SRC_NAME ${SRC} NAME_WE)
|
||||||
# add_executable(${SRC_NAME} ${SRC})
|
add_executable(${SRC_NAME} ${SRC})
|
||||||
# target_link_libraries(${SRC_NAME} GTest::GTest GTest::Main m4ri m4rie)
|
target_link_libraries(${SRC_NAME} GTest::GTest GTest::Main m4ri m4rie)
|
||||||
# gtest_discover_tests(${SRC_NAME})
|
gtest_discover_tests(${SRC_NAME})
|
||||||
# endforeach()
|
endforeach()
|
||||||
|
29
test/test_gfp_elim.cu
Normal file
29
test/test_gfp_elim.cu
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include "test_header.cuh"
|
||||||
|
|
||||||
|
using namespace gfp;
|
||||||
|
|
||||||
|
bool test_gfp_elim(size_t rank, size_t rank_col, size_t nrows, size_t ncols, uint_fast32_t seed)
|
||||||
|
{
|
||||||
|
MatGFP rdc(rank, ncols);
|
||||||
|
rdc.randomize(rank_col, seed);
|
||||||
|
MatGFP mix(nrows, rank);
|
||||||
|
mix.randomize(seed);
|
||||||
|
MatGFP a = mix * rdc;
|
||||||
|
ElimResult res = a.gpu_elim();
|
||||||
|
MatGFP win(a, 0, 0, res.rank, a.width);
|
||||||
|
return rdc == win;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestGFPMul, Small)
|
||||||
|
{
|
||||||
|
uint_fast32_t seed = 41921095;
|
||||||
|
EXPECT_TRUE(test_gfp_elim(5, 6, 7, 8, seed));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestGFPMul, Mediem)
|
||||||
|
{
|
||||||
|
uint_fast32_t seed = 41921095;
|
||||||
|
EXPECT_TRUE(test_gfp_elim(50, 60, 70, 80, seed));
|
||||||
|
EXPECT_TRUE(test_gfp_elim(500, 600, 700, 800, seed));
|
||||||
|
}
|
40
test/test_interface.cu
Normal file
40
test/test_interface.cu
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include "test_header.cuh"
|
||||||
|
#include "interface.cuh"
|
||||||
|
|
||||||
|
using namespace gf256;
|
||||||
|
|
||||||
|
bool test_gf256_elim_interface(size_t rank, size_t rank_col, size_t nrows, size_t ncols, const GF256 &gf256, uint_fast32_t seed)
|
||||||
|
{
|
||||||
|
assert(rank <= nrows && rank <= rank_col && rank_col <= ncols);
|
||||||
|
MatGF256 rdc(rank, ncols);
|
||||||
|
rdc.randomize(rank_col, seed);
|
||||||
|
MatGF256 mix(nrows, rank);
|
||||||
|
mix.randomize(seed);
|
||||||
|
MatGF256 src = gpu_mul(mix, rdc, gf256);
|
||||||
|
|
||||||
|
gf2e *ff_m4rie = gf2e_init(gf256.poly());
|
||||||
|
mzed_t *A_m4rie = mzed_init(ff_m4rie, src.nrows, src.ncols);
|
||||||
|
mzedwrite(src, A_m4rie);
|
||||||
|
mzed_t *A_m4rie_copy = mzed_copy(NULL, A_m4rie);
|
||||||
|
|
||||||
|
base_t rank_interface = gpu_mzed_elim(A_m4rie);
|
||||||
|
rci_t rank_m4rie = mzed_echelonize_newton_john(A_m4rie_copy, 1);
|
||||||
|
|
||||||
|
return (rank_interface == rank_m4rie) && (mzed_cmp(A_m4rie, A_m4rie_copy) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestInterface, Small)
|
||||||
|
{
|
||||||
|
uint_fast32_t seed = 41921095;
|
||||||
|
GF256 gf256(0b100011101);
|
||||||
|
EXPECT_TRUE(test_gf256_elim_interface(5, 7, 6, 8, gf256, seed));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestInterface, Mediem)
|
||||||
|
{
|
||||||
|
uint_fast32_t seed = 41921095;
|
||||||
|
GF256 gf256(0b100011101);
|
||||||
|
EXPECT_TRUE(test_gf256_elim_interface(50, 70, 60, 80, gf256, seed));
|
||||||
|
EXPECT_TRUE(test_gf256_elim_interface(500, 700, 600, 800, gf256, seed));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user